From f0bf8c399c354c22227f8f1a76ed806098db59c0 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期二, 21 五月 2024 16:51:02 +0800
Subject: [PATCH] 2024-05-21

---
 src/templates/zshare/modalform/index.jsx                                           |   11 
 src/tabviews/custom/components/iframe/index.scss                                   |    1 
 src/tabviews/custom/components/editor/braft-editor/index.jsx                       |   31 
 src/tabviews/zshare/actionList/tabbutton/index.scss                                |   18 
 src/menu/components/card/balcony/options.jsx                                       |    1 
 src/tabviews/zshare/settingcomponent/index.jsx                                     |    8 
 src/templates/zshare/verifycard/customscript/index.jsx                             |   85 
 src/tabviews/custom/popview/index.jsx                                              |   98 
 src/views/systemfunc/header/index.jsx                                              |    9 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx  |    4 
 src/tabviews/zshare/mutilform/mkNumberInput/index.jsx                              |   10 
 src/menu/components/table/edit-table/columns/editColumn/index.jsx                  |   75 
 src/tabviews/zshare/actionList/changeuserbutton/index.jsx                          |   34 
 src/menu/components/table/edit-table/columns/tableIn/index.scss                    |    4 
 src/menu/datasource/verifycard/index.jsx                                           |   86 
 src/assets/css/main.scss                                                           |   17 
 src/menu/components/card/table-card/index.scss                                     |    1 
 src/components/header/index.scss                                                   |   35 
 src/tabviews/custom/components/module/invoice/subTable/index.scss                  |    0 
 src/views/interface/header/index.jsx                                               |    4 
 src/menu/components/card/cardcellcomponent/index.jsx                               |   71 
 src/menu/components/form/tab-form/index.jsx                                        |    3 
 src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx               |  474 +
 src/menu/components/search/main-search/dragsearch/card.jsx                         |    4 
 src/tabviews/zshare/actionList/funcMegvii/index.jsx                                |   64 
 src/menu/components/card/cardcomponent/index.jsx                                   |  128 
 src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss               |    5 
 src/tabviews/custom/components/chart/antv-X6/index.jsx                             |  124 
 src/menu/components/card/prop-card/index.jsx                                       |    7 
 src/templates/zshare/customscript/index.jsx                                        |    2 
 src/menu/components/table/edit-table/columns/index.jsx                             |    2 
 src/menu/components/module/voucher/voucherTable/index.scss                         |    3 
 src/menu/datasource/verifycard/utils.jsx                                           |    9 
 src/tabviews/custom/components/chart/antv-bar-line/index.jsx                       |   62 
 src/assets/css/viewstyle.scss                                                      |   10 
 src/tabviews/custom/components/chart/antv-dashboard/index.jsx                      |   30 
 src/views/login/loginform.jsx                                                      |   11 
 src/views/menudesign/popview/index.jsx                                             |    4 
 src/menu/components/module/invoice/verifycard/baseform/index.scss                  |    0 
 src/menu/datasource/verifycard/index.scss                                          |    5 
 src/tabviews/zshare/topSearch/index.jsx                                            |   88 
 src/menu/components/card/prop-card/index.scss                                      |    2 
 src/menu/components/card/doublecardcomponent/index.scss                            |   13 
 src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx                   |    4 
 src/menu/components/chart/chart-custom/index.jsx                                   |   11 
 src/menu/components/card/cardsimplecomponent/options.jsx                           |   28 
 src/menu/components/form/simple-form/index.jsx                                     |    8 
 src/tabviews/custom/components/table/edit-table/index.jsx                          |  221 
 src/api/index.js                                                                   |   19 
 src/tabviews/zshare/topSearch/index.scss                                           |    7 
 src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx                 |   17 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx             |    2 
 src/tabviews/custom/components/iframe/index.jsx                                    |   29 
 src/menu/components/table/base-table/columns/editColumn/index.jsx                  |   63 
 src/menu/components/share/searchcomponent/index.scss                               |   11 
 src/tabviews/zshare/tablenodes/index.jsx                                           |    6 
 src/tabviews/custom/components/carousel/cardItem/index.jsx                         |   27 
 src/views/pcdesign/index.jsx                                                       |   14 
 src/menu/datasource/verifycard/settingform/index.jsx                               |   15 
 src/views/systemfunc/sidemenu/index.jsx                                            |    4 
 src/menu/components/share/actioncomponent/index.jsx                                |   17 
 src/menu/components/card/cardsimplecomponent/index.jsx                             |  107 
 src/tabviews/custom/components/module/account/index.scss                           |    3 
 src/tabviews/custom/components/form/step-form/index.jsx                            |   58 
 src/menu/components/module/account/index.jsx                                       |    2 
 src/views/appmanage/header/index.jsx                                               |    7 
 src/menu/components/module/account/index.scss                                      |    2 
 src/tabviews/custom/components/tree/antd-tree/index.jsx                            |  128 
 src/tabviews/zshare/actionList/popupbutton/index.jsx                               |   51 
 src/tabviews/zshare/normalTable/index.jsx                                          |   35 
 src/menu/components/share/searchcomponent/index.jsx                                |   13 
 src/templates/comtableconfig/updatetable/index.jsx                                 |    6 
 src/views/mkiframe/index.jsx                                                       |   28 
 src/tabviews/custom/components/group/normal-group/index.scss                       |  103 
 src/menu/datasource/index.jsx                                                      |    4 
 src/tabviews/zshare/automatic/index.jsx                                            |    6 
 src/menu/components/module/voucher/index.jsx                                       |   23 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx              |    6 
 src/menu/components/tree/antd-tree/index.jsx                                       |   24 
 src/views/billprint/index.jsx                                                      |   39 
 src/tabviews/subtabtable/index.jsx                                                 |   20 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                              |  118 
 src/menu/header/index.jsx                                                          |    6 
 src/assets/img/wx-icon.png                                                         |    0 
 src/views/menudesign/index.jsx                                                     |   32 
 src/menu/modulesource/option.jsx                                                   |    2 
 src/tabviews/custom/components/card/data-card/index.jsx                            |   94 
 src/menu/components/module/invoice/options.jsx                                     |   88 
 src/tabviews/custom/components/module/voucher/index.jsx                            |  301 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx                  |    2 
 src/templates/zshare/pasteform/index.jsx                                           |    2 
 src/menu/components/card/doublecardcomponent/index.jsx                             |  128 
 src/menu/components/card/data-card/index.jsx                                       |   15 
 src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx                      |   12 
 src/menu/components/card/cardcellcomponent/elementform/index.scss                  |    9 
 src/menu/components/carousel/data-card/index.scss                                  |    2 
 src/menu/components/search/main-search/options.jsx                                 |   15 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss             |    9 
 src/tabviews/zshare/actionList/index.scss                                          |   13 
 src/components/tabview/index.scss                                                  |   12 
 src/templates/sharecomponent/actioncomponent/formconfig.jsx                        |    6 
 src/menu/components/card/doublecardcomponent/options.jsx                           |   15 
 src/menu/components/table/normal-table/options.jsx                                 |  110 
 src/menu/components/tree/antd-tree/index.scss                                      |   10 
 src/components/header/index.jsx                                                    |   35 
 src/tabviews/custom/components/card/double-data-card/index.jsx                     |   70 
 src/templates/zshare/verifycard/callbackcustomscript/index.jsx                     |    2 
 src/tabviews/custom/components/card/cardItem/index.jsx                             |   47 
 src/mob/components/topbar/normal-navbar/options.jsx                                |    2 
 src/tabviews/custom/components/carousel/data-card/index.jsx                        |   34 
 src/templates/sharecomponent/fieldscomponent/index.jsx                             |    2 
 src/components/normalform/modalform/mkTable/index.jsx                              |    4 
 src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx       |  299 +
 src/tabviews/custom/components/tree/antd-tree/index.scss                           |   54 
 src/tabviews/custom/components/chart/custom-chart/index.jsx                        |   34 
 src/menu/components/card/balcony/index.jsx                                         |    2 
 src/tabviews/zshare/actionList/tabbutton/index.jsx                                 |  174 
 src/templates/modalconfig/index.scss                                               |    6 
 src/components/normalform/modalform/index.jsx                                      |   20 
 src/menu/stylecontroller/index.jsx                                                 |  101 
 src/menu/components/table/base-table/options.jsx                                   |   61 
 src/tabviews/custom/components/module/voucher/voucherTable/index.scss              |    3 
 src/templates/zshare/verifycard/index.jsx                                          |   25 
 src/menu/modulecell/index.jsx                                                      |    1 
 src/tabviews/zshare/actionList/printbutton/index.jsx                               |   47 
 src/tabviews/custom/components/table/edit-table/normalTable/index.scss             |    8 
 src/menu/components/card/cardcellcomponent/formconfig.jsx                          |  157 
 src/tabviews/custom/components/module/invoice/subTable/index.jsx                   |  250 
 src/tabviews/custom/components/module/voucher/index.scss                           |   71 
 src/components/normalform/modalform/mkTable/index.scss                             |   17 
 src/menu/components/module/voucher/index.scss                                      |   47 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx   |   18 
 src/mob/header/index.jsx                                                           |    7 
 src/mob/searchconfig/index.jsx                                                     |    3 
 src/menu/components/tree/antd-tree/options.jsx                                     |   25 
 src/tabviews/custom/components/module/voucher/resetRemark/index.jsx                |    4 
 src/tabviews/zshare/actionList/funcbutton/index.jsx                                |  344 +
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx               |  227 
 src/views/basedesign/updateFormTab/index.jsx                                       |    6 
 src/menu/components/card/cardcellcomponent/index.scss                              |    7 
 src/menu/components/card/cardcellcomponent/dragaction/action.jsx                   |   14 
 src/menu/components/card/cardcellcomponent/elementform/index.jsx                   |  315 
 src/menu/components/table/edit-table/options.jsx                                   |   15 
 src/menu/stylecontroller/index.scss                                                |   16 
 src/templates/modalconfig/index.jsx                                                |    2 
 src/templates/sharecomponent/searchcomponent/searchform/index.scss                 |    8 
 src/tabviews/custom/components/form/step-form/index.scss                           |   20 
 src/tabviews/zshare/actionList/newpagebutton/index.jsx                             |  147 
 src/menu/components/module/invoice/verifycard/index.scss                           |  124 
 src/tabviews/commontable/index.jsx                                                 |   28 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx               |   45 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx             |  120 
 src/menu/components/form/formaction/formconfig.jsx                                 |   42 
 src/menu/components/card/cardsimplecomponent/index.scss                            |   13 
 src/menu/components/share/normalheader/index.scss                                  |    5 
 src/tabviews/custom/components/card/cardcellList/index.jsx                         |  275 
 src/tabviews/custom/components/card/prop-card/index.jsx                            |   60 
 src/tabviews/zshare/actionList/funczip/index.jsx                                   |   58 
 src/menu/components/card/data-card/options.jsx                                     |  138 
 src/tabviews/custom/components/table/normal-table/index.jsx                        |  253 
 src/tabviews/custom/components/chart/antv-pie/index.jsx                            |   30 
 src/tabviews/custom/components/timeline/normal-timeline/index.jsx                  |   33 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx              |  113 
 src/components/breadview/index.jsx                                                 |  112 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss                 |   39 
 src/tabviews/custom/components/module/invoice/index.scss                           |  361 +
 src/tabviews/zshare/mutilform/index.jsx                                            |   37 
 src/menu/components/share/actioncomponent/actionform/index.jsx                     |  187 
 src/tabviews/custom/index.jsx                                                      |  151 
 src/menu/components/card/cardcomponent/index.scss                                  |   13 
 src/menu/components/module/invoice/verifycard/index.jsx                            |  696 ++
 src/menu/components/module/invoice/index.scss                                      |  272 
 src/menu/components/table/normal-table/columns/index.jsx                           |    2 
 src/assets/img/invoice.png                                                         |    0 
 src/tabviews/zshare/mutilform/mkDatePicker/index.jsx                               |   13 
 src/tabviews/treepage/index.jsx                                                    |    6 
 src/tabviews/custom/components/chart/antv-scatter/index.jsx                        |   34 
 src/menu/components/card/cardcellcomponent/dragaction/index.scss                   |    7 
 src/views/design/header/index.jsx                                                  |    5 
 src/views/printTemplate/index.jsx                                                  |   13 
 src/tabviews/custom/components/module/account/index.jsx                            |    4 
 src/menu/components/form/formaction/actionform/index.jsx                           |   50 
 src/tabviews/custom/components/chart/antv-G6/index.jsx                             |   58 
 src/menu/components/card/cardcellcomponent/dragaction/index.jsx                    |   12 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx             |   26 
 src/tabviews/zshare/actionList/exceloutbutton/index.jsx                            |  279 
 src/views/design/sidemenu/thdmenuform/index.jsx                                    |    2 
 src/menu/components/card/cardcellcomponent/dragaction/card.jsx                     |   18 
 src/menu/components/card/balcony/index.scss                                        |    2 
 src/views/tabledesign/index.jsx                                                    |   19 
 src/tabviews/zshare/actionList/index.jsx                                           |   26 
 src/tabviews/custom/components/form/simple-form/index.jsx                          |   33 
 src/tabviews/subtable/index.jsx                                                    |   20 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.scss   |    0 
 src/views/rolemanage/header/index.jsx                                              |    7 
 src/menu/components/table/edit-table/index.jsx                                     |   32 
 src/menu/components/group/normal-group/index.scss                                  |    2 
 src/tabviews/custom/components/card/table-card/index.jsx                           |  131 
 src/menu/components/module/invoice/verifycard/customscript/index.scss              |    0 
 src/menu/components/module/voucher/options.jsx                                     |   22 
 src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx                 |   52 
 src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx                     |   14 
 src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx        |    1 
 src/menu/components/form/step-form/index.jsx                                       |    3 
 public/manifest.json                                                               |    2 
 src/menu/components/share/normalheader/index.jsx                                   |   25 
 src/templates/modalconfig/settingform/index.jsx                                    |   23 
 src/views/mobdesign/popview/index.jsx                                              |    4 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.jsx    |  132 
 src/menu/components/search/main-search/index.jsx                                   |    7 
 src/tabviews/custom/components/module/voucher/voucherTable/index.jsx               |  100 
 src/views/login/index.scss                                                         |    6 
 src/menu/components/table/edit-table/columns/tableIn/customscript/index.jsx        |    4 
 src/tabviews/zshare/topSearch/mkDatePicker/index.jsx                               |   15 
 src/views/login/index.jsx                                                          |   24 
 src/utils/utils-datamanage.js                                                      |   58 
 src/tabviews/custom/components/code/sand-box/index.jsx                             |   30 
 src/menu/components/table/edit-table/columns/tableIn/index.jsx                     |    6 
 src/tabviews/zshare/actionList/editLine/index.jsx                                  |   27 
 src/menu/components/card/table-card/index.jsx                                      |    9 
 src/templates/zshare/verifycard/baseform/index.scss                                |   10 
 src/utils/utils-custom.js                                                          |   63 
 src/tabviews/custom/components/share/normalTable/index.scss                        |   16 
 src/tabviews/zshare/actionList/excelInbutton/index.jsx                             |   80 
 src/menu/components/share/searchcomponent/dragsearch/card.jsx                      |   14 
 src/templates/modalconfig/checkCard/index.jsx                                      |    4 
 src/menu/components/table/normal-table/columns/editColumn/index.jsx                |   80 
 src/tabviews/basetable/index.jsx                                                   |   65 
 src/menu/components/card/data-card/index.scss                                      |    2 
 src/tabviews/custom/components/module/invoice/index.jsx                            | 1284 ++++
 src/menu/menushell/card.jsx                                                        |    3 
 src/templates/modalconfig/dragelement/card.jsx                                     |    2 
 src/views/mobdesign/index.jsx                                                      |   14 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss              |    4 
 src/menu/components/module/invoice/verifycard/customscript/index.jsx               |  284 +
 src/menu/components/card/double-data-card/options.jsx                              |   12 
 src/tabviews/zshare/actionList/funcbutton/index.scss                               |    0 
 src/menu/components/module/invoice/verifycard/baseform/index.jsx                   |  181 
 src/menu/components/module/invoice/index.jsx                                       |  495 +
 src/menu/components/share/actioncomponent/actionform/index.scss                    |   11 
 src/menu/components/share/actioncomponent/formconfig.jsx                           |  502 +
 src/tabviews/custom/components/group/normal-group/index.jsx                        |   30 
 src/menu/components/group/normal-group/options.jsx                                 |   28 
 src/views/appcheck/header/index.jsx                                                |    7 
 src/tabviews/custom/components/carousel/prop-card/index.jsx                        |   60 
 src/menu/debug/index.jsx                                                           |   78 
 src/tabviews/zshare/topSearch/advanceform/index.scss                               |    7 
 src/menu/components/table/normal-table/index.jsx                                   |   56 
 src/menu/components/card/cardcomponent/options.jsx                                 |    5 
 src/tabviews/zshare/normalTable/index.scss                                         |    5 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx                  |    3 
 src/components/tabview/index.jsx                                                   |   77 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx           |  123 
 src/tabviews/custom/components/table/base-table/index.jsx                          |   41 
 src/menu/components/timeline/normal-timeline/index.scss                            |    2 
 src/tabviews/custom/components/card/double-data-card/index.scss                    |    6 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx |    8 
 src/menu/components/carousel/prop-card/index.scss                                  |    2 
 src/menu/components/module/invoice/verifycard/callbackcustomscript/index.scss      |    0 
 src/menu/datasource/verifycard/customscript/index.jsx                              |    6 
 src/templates/sharecomponent/searchcomponent/index.jsx                             |    8 
 src/tabviews/custom/components/module/invoice/invoiceTable/index.scss              |  131 
 src/tabviews/custom/components/calendar/index.jsx                                  |   33 
 src/tabviews/custom/components/share/normalheader/index.scss                       |    4 
 src/tabviews/custom/components/share/normalTable/index.jsx                         |  156 
 src/menu/components/form/step-form/options.jsx                                     |   20 
 src/components/breadview/index.scss                                                |   12 
 src/tabviews/custom/components/card/data-card/index.scss                           |    9 
 src/tabviews/zshare/actionList/exportPdf/index.jsx                                 |   30 
 src/utils/utils.js                                                                 |  378 
 src/tabviews/custom/components/card/table-card/index.scss                          |   21 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx                  |   33 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx              |  300 
 src/index.js                                                                       |   18 
 src/tabviews/custom/components/form/tab-form/index.jsx                             |   33 
 src/tabviews/custom/components/share/tabtransfer/index.jsx                         |    4 
 src/tabviews/debugtable/index.jsx                                                  |    2 
 src/templates/treepageconfig/updatetable/index.jsx                                 |    6 
 src/templates/zshare/formconfig.jsx                                                |   47 
 src/tabviews/custom/components/interfaces/interItem/index.jsx                      |   30 
 src/tabviews/custom/components/module/voucher/resetAttach/index.jsx                |    7 
 src/tabviews/zshare/flowFloat/index.jsx                                            |    6 
 src/tabviews/custom/components/chart/antv-X6/index.scss                            |   32 
 /dev/null                                                                          |  193 
 src/menu/modalconfig/index.scss                                                    |   18 
 src/menu/modalconfig/index.jsx                                                     |    2 
 src/tabviews/custom/components/card/balcony/index.jsx                              |   57 
 src/tabviews/custom/components/card/cardcellList/index.scss                        |   27 
 src/templates/zshare/verifycard/baseform/index.jsx                                 |   86 
 src/menu/components/card/double-data-card/index.scss                               |    2 
 src/views/tabledesign/popview/index.jsx                                            |    4 
 291 files changed, 12,778 insertions(+), 3,744 deletions(-)

diff --git a/public/manifest.json b/public/manifest.json
index f3adf88..6f976ee 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -6,5 +6,5 @@
   "display": "standalone",
   "theme_color": "#000000",
   "background_color": "#ffffff",
-  "mk_version": "20240302"
+  "mk_version": "20240501"
 }
diff --git a/src/api/index.js b/src/api/index.js
index 193a164..7e86947 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -467,7 +467,7 @@
 
         this.getSystemConfig(param).then(res => {
           if (!res.status) {
-            reject()
+            reject(res.message)
             return
           }
 
@@ -507,7 +507,7 @@
 
           CacheUtils.updateIndexDBversion({version: res.app_version || '1.00', createDate: curTime})
 
-          resolve()
+          resolve(list)
         })
       }, () => {
         reject()
@@ -1127,6 +1127,21 @@
     })
   }
 
+  /**
+   * @description 寰俊鏀粯閫�娆�
+   */
+  setRefund (orderId) {
+    let _param = new FormData()
+    _param.append('out_biz_no', orderId)
+
+    return axios({
+      url: '/wxpay/wxRefund',
+      headers: { 'Content-Type': 'multipart/form-data' },
+      method: 'post',
+      data: _param
+    })
+  }
+
   postekPrint (data) {
     return axios({
       url: 'http://127.0.0.1:888/postek/print',
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 545d3c2..41db689 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -100,9 +100,15 @@
   color: unset;
 }
 
-// 閲嶇疆鎸夐挳涓枃瀛椾笌鍥炬爣璺濈
-.ant-btn > .anticon + span, .ant-btn > span + .anticon {
-  margin-left: 5px;
+// 閲嶇疆鎸夐挳鍔犺浇涓牱寮�
+.ant-btn.ant-btn-loading .anticon:not(.anticon-loading) {
+  transition: all 0.3s;
+}
+.ant-btn.ant-btn-loading >.anticon-loading + span .anticon, .ant-btn.ant-btn-loading >.anticon-loading + .anticon {
+  width: 0;
+  opacity: 0;
+  margin-left: 0px!important;
+  margin-right: 0px!important;
 }
 
 // 璁剧疆涓嬫媺鎼滅储婊氬姩鏉℃牱寮�
@@ -762,4 +768,9 @@
   .ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked):not(.ant-radio-button-wrapper-disabled):hover {
     color: var(--mk-sys-color);
   }
+}
+
+// 榧犳爣鎮诞澧炲姞涓嬪垝绾�
+.mk-hover-underline:hover {
+  text-decoration: underline!important;
 }
\ No newline at end of file
diff --git a/src/assets/css/viewstyle.scss b/src/assets/css/viewstyle.scss
index 4dee396..258b3c2 100644
--- a/src/assets/css/viewstyle.scss
+++ b/src/assets/css/viewstyle.scss
@@ -162,8 +162,10 @@
     border-color: $color6;
   }
   // 涓嬫媺妗�
-  .ant-select-selection:hover {
-    border-color: $color5;
+  .ant-select:not(.ant-select-disabled) {
+    .ant-select-selection:hover {
+      border-color: $color5;
+    }
   }
   .ant-select-focused .ant-select-selection, .ant-select-selection:focus, .ant-select-selection:active {
     border-color: $color5;
@@ -174,7 +176,7 @@
     background-color: $color6;
   }
   // 杈撳叆妗�
-  .ant-input:hover {
+  .ant-input:not([disabled]):hover {
     border-color: $color5;
   }
   .ant-input:focus, .ant-input:active {
@@ -185,7 +187,7 @@
     border-color: $color5;
     box-shadow: 0 0 0 2px $color2;
   }
-  .ant-input-number:hover, .ant-input-number:focus, .ant-input-number:active, .ant-input-number-input:hover, .ant-input-number-input:focus, .ant-input-number-input:active, .ant-input-number-focused:hover, .ant-input-number-focused:focus, .ant-input-number-focused:active {
+  .ant-input-number:not(.ant-input-number-disabled):hover, .ant-input-number:focus, .ant-input-number:active, .ant-input-number-input:hover, .ant-input-number-input:focus, .ant-input-number-input:active, .ant-input-number-focused:hover, .ant-input-number-focused:focus, .ant-input-number-focused:active {
     border-color: $color5;
   }
   .ant-input-number:focus, .ant-input-number:active {
diff --git a/src/assets/img/invoice.png b/src/assets/img/invoice.png
new file mode 100644
index 0000000..3a5185d
--- /dev/null
+++ b/src/assets/img/invoice.png
Binary files differ
diff --git a/src/assets/img/wx-icon.png b/src/assets/img/wx-icon.png
new file mode 100644
index 0000000..e344540
--- /dev/null
+++ b/src/assets/img/wx-icon.png
Binary files differ
diff --git a/src/components/breadview/index.jsx b/src/components/breadview/index.jsx
index 3a44900..44494c8 100644
--- a/src/components/breadview/index.jsx
+++ b/src/components/breadview/index.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
-import { BackTop, Breadcrumb, notification} from 'antd'
-import { HomeOutlined, RightOutlined, RedoOutlined } from '@ant-design/icons'
+import { BackTop, Breadcrumb, notification, Modal } from 'antd'
+import { HomeOutlined, RightOutlined, RedoOutlined, LoadingOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import 'moment/locale/zh-cn'
 
@@ -22,8 +22,38 @@
 
 class BreadView extends Component {
   state = {
-    tabview: null, // 鏍囩
-    hasNavBar: window.GLOB.navBar === 'linkage_navigation'
+    tabview: null,
+    hasNavBar: window.GLOB.navBar === 'linkage_navigation',
+    visible: false
+  }
+
+  reloading = false
+
+  UNSAFE_componentWillMount () {
+    let home = {
+      MenuID: 'home_page_id',
+      MenuName: '棣栭〉',
+      type: 'Home'
+    }
+    this.setState({tabview: home})
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('modifyTabs', this.modifyTabs)
+    if (window.GLOB.forcedUpdate) {
+      MKEmitter.addListener('reloadTabs', this.reloadTabs)
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadTabs', this.reloadTabs)
+    MKEmitter.removeListener('modifyTabs', this.modifyTabs)
   }
 
   refreshTabview = () => {
@@ -105,15 +135,6 @@
     }
   }
 
-  UNSAFE_componentWillMount () {
-    let home = {
-      MenuID: 'home_page_id',
-      MenuName: '棣栭〉',
-      type: 'Home'
-    }
-    this.setState({tabview: home})
-  }
-
   gotoHome = () => {
     let home = {
       MenuID: 'home_page_id',
@@ -134,22 +155,48 @@
     }
   }
 
-  componentDidMount () {
-    MKEmitter.addListener('modifyTabs', this.modifyTabs)
-  }
+  reloadTabs = () => {
+    if (this.reloading) return
 
-  /**
-   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
-   */
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('modifyTabs', this.modifyTabs)
+    this.reloading = true
+    let time = new Date().getTime()
+
+    this.setState({visible: true})
+
+    Api.getAppVersion(true).then((list) => {
+      let _time = new Date().getTime()
+      let delay = _time - time
+      delay = delay < 3000 ? 3000 - delay : 0
+
+      setTimeout(() => {
+        this.setState({visible: false})
+        this.reloading = false
+  
+        Modal.success({
+          title: '鏇存柊鎴愬姛銆�',
+        })
+  
+        if (list && list.length && list.includes(this.state.tabview.MenuID)) {
+          MKEmitter.emit('reloadMenuView', this.state.tabview.MenuID)
+        }
+      }, delay)
+    }, (message) => {
+      let _time = new Date().getTime()
+      let delay = _time - time
+      delay = delay < 3000 ? 3000 - delay : 0
+
+      setTimeout(() => {
+        this.setState({visible: false})
+        this.reloading = false
+        Modal.error({
+          title: message || '绯荤粺閰嶇疆鏇存柊澶辫触锛�',
+        })
+      }, delay)
+    })
   }
 
   render () {
-    const { tabview, hasNavBar } = this.state
+    const { tabview, hasNavBar, visible } = this.state
 
     return (
       <section id="mk-tabgroup-wrap" className="mk-breadview-wrap">
@@ -175,6 +222,21 @@
             </div>
           </div>
         </BackTop>
+        <Modal
+          visible={visible}
+          width={400}
+          closable={false}
+          centered={true}
+          footer={null}
+          destroyOnClose
+        >
+          <div className="mk-menus-update">
+            <div className="tip">
+              绯荤粺鏇存柊涓紝璇风◢鍚�
+            </div>
+            <LoadingOutlined />
+          </div>
+        </Modal>
       </section>
     )
   }
diff --git a/src/components/breadview/index.scss b/src/components/breadview/index.scss
index bf7a267..d178db3 100644
--- a/src/components/breadview/index.scss
+++ b/src/components/breadview/index.scss
@@ -46,4 +46,16 @@
 .ant-message {
   top: 50px;
   z-index: 1080;
+}
+
+.mk-menus-update {
+  text-align: center;
+  font-size: 20px;
+  color: #131313;
+  .tip {
+    margin-bottom: 10px;
+  }
+  .anticon {
+    color: var(--mk-sys-color);
+  }
 }
\ No newline at end of file
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index 80a849c..6151dc5 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -10,6 +10,7 @@
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import avatar from '@/assets/img/avatar.jpg'
+import wxicon from '@/assets/img/wx-icon.png'
 import './index.scss'
 
 const { confirm } = Modal
@@ -24,6 +25,7 @@
     userName: '',
     fullName: '',
     logourl: window.GLOB.mainlogo,
+    wxVisible: false,
     loginVisible: false,
     loginLoading: false,
     avatar: Utils.getrealurl(sessionStorage.getItem('avatar')),
@@ -336,6 +338,7 @@
                   trdItem.OpenType = PageParam.OpenType || 'newtab'
                   trdItem.hidden = PageParam.hidden || 'false'
                   trdItem.menuColor = PageParam.menuColor || ''
+                  trdItem.urlFields = PageParam.urlFields || ''
 
                   if (trdItem.type === 'NewPage') {
                     trdItem.OpenType = 'newpage'
@@ -435,6 +438,8 @@
           sessionStorage.setItem('CloudAvatar', res.icon)
           sessionStorage.setItem('cloudDataM', res.dataM ? 'true' : '')
           sessionStorage.setItem('cloudRole_id', res.role_id || '')
+
+          sessionStorage.setItem('CloudLogo', res.open_logo || '')
 
           let _url = window.location.href.split('#')[0] + 'cloud'
           if (param.remember) {
@@ -594,14 +599,6 @@
     })
   }
 
-  wxnotice = () => {
-    Modal.success({
-      className: 'mk-wx-notice',
-      title: <QrCode card={{qrWidth: 320, color: '#000000'}} value={window.GLOB.baseurl + 'mob/wxnotice.html?userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID')}/>,
-      okText: '鍏抽棴'
-    })
-  }
-
   changeToHome = () => {
     if (!['linkage', 'menu_board'].includes(window.GLOB.navBar)) return
 
@@ -628,7 +625,7 @@
         <Menu.Item key="verup" onClick={this.verup}>
           椤甸潰鏇存柊
         </Menu.Item>
-        {window.GLOB.WXNotice ? <Menu.Item key="wxnotice" onClick={this.wxnotice}>
+        {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}>
@@ -801,6 +798,26 @@
         </Modal>
         {/* 淇敼瀵嗙爜 */}
         <Resetpwd />
+        {/* 寰俊娑堟伅 */}
+        <Modal
+          wrapClassName="mk-wx-sms-modal"
+          visible={this.state.wxVisible}
+          title="鎵爜鍏虫敞  鎺ユ敹娑堟伅"
+          width={400}
+          centered={true}
+          onCancel={() => this.setState({wxVisible: false})}
+          footer={null}
+          destroyOnClose
+        >
+          <div className="wx-sms-wrap">
+            <QrCode card={{qrWidth: 200, color: '#000000'}} value={window.GLOB.baseurl + 'mob/wxnotice.html?userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID')}/>
+            <div className="tip">
+              <img src={wxicon} alt=""/>
+              <span>寰俊鎵爜</span>
+              <span>鍏虫敞鍏紬鍙�</span>
+            </div>
+          </div>
+        </Modal>
       </header>
     )
   }
diff --git a/src/components/header/index.scss b/src/components/header/index.scss
index dc9c47d..751fa9a 100644
--- a/src/components/header/index.scss
+++ b/src/components/header/index.scss
@@ -276,17 +276,34 @@
   }
 }
 
-.mk-wx-notice {
-  top: 100px!important;
-  .anticon-check-circle {
-    display: none;
-  }
-  .ant-modal-confirm-title {
+.mk-wx-sms-modal {
+  .ant-modal-title {
     text-align: center;
-    min-height: 320px;
+    font-size: 22px;
+    font-weight: 500;
+    color: #151515;
+    margin-top: 15px;
+    letter-spacing: 2px;
   }
-  .ant-modal-confirm-btns {
-    float: none!important;
+  .wx-sms-wrap {
     text-align: center;
+  
+    .tip {
+      margin: 15px;
+      img {
+        width: 24px;
+        margin-right: 10px;
+      }
+      span {
+        font-size: 16px;
+        letter-spacing: 2px;
+        font-weight: 500;
+        color: #333;
+      }
+      span + span {
+        color: #45B449;
+        font-weight: bold;
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index 776c225..8a7599f 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -18,6 +18,7 @@
 const MKCheckbox = asyncComponent(() => import('./mkCheckbox'))
 const StyleInput = asyncComponent(() => import('./styleInput'))
 const MKFileUpload = asyncComponent(() => import('@/tabviews/zshare/fileupload'))
+const MkPrintTemps = asyncComponent(() => import('@/menu/components/share/actioncomponent/actionform/mkPrintTemps'))
 const MKColor = asyncComponent(() => import('@/mob/colorsketch'))
 // const MKColor = asyncComponent(() => import('@/tabviews/zshare/mutilform/mkColor'))
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
@@ -279,7 +280,14 @@
       if (item.hidden || item.forbid) return
 
       let content = null
-      let label = item.tooltip ? <Tooltip placement="topLeft" title={item.tooltip}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip> : item.label
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
     
       if (item.type === 'text') {
         content = (<MKEInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val}, item)} onSubmit={this.props.inputSubmit} />)
@@ -314,14 +322,22 @@
           </Col>
         )
         return
+      } else if (item.type === 'printTemps') {
+        content = <MkPrintTemps onChange={(val) => this.recordChange({[item.field]: val})}/>
       }
 
       if (!content) return
 
       if (item.help) {
+        let help = null
+        if (typeof(item.help) === 'function') {
+          help = item.help(this.record)
+        } else {
+          help = <span style={{fontSize: '12px'}}>{item.help}</span>
+        }
         fields.push(
           <Col span={item.span || 12} key={index}>
-            <Form.Item label={label} help={<span style={{fontSize: '12px'}}>{item.help}</span>}>
+            <Form.Item label={label} help={help}>
               {getFieldDecorator(item.field, {
                 initialValue: item.initval,
                 rules: item.rules
diff --git a/src/components/normalform/modalform/mkTable/index.jsx b/src/components/normalform/modalform/mkTable/index.jsx
index 341e32a..0ae8cfa 100644
--- a/src/components/normalform/modalform/mkTable/index.jsx
+++ b/src/components/normalform/modalform/mkTable/index.jsx
@@ -352,6 +352,10 @@
         if (_options.length) {
           col.extends.forEach(n => {
             record[n.value] = _options.map(o => o[n.key]).join(' / ')
+
+            if (n.mutilLabel && !record[n.mutilLabel]) {
+              record[n.mutilLabel] = _options[_options.length - 1][n.key]
+            }
           })
         }
       } else {
diff --git a/src/components/normalform/modalform/mkTable/index.scss b/src/components/normalform/modalform/mkTable/index.scss
index a5620f0..97e3e85 100644
--- a/src/components/normalform/modalform/mkTable/index.scss
+++ b/src/components/normalform/modalform/mkTable/index.scss
@@ -23,6 +23,23 @@
       top: 4px;
       white-space: nowrap;
     }
+    .mini-color {
+      .color-sketch-block {
+        width: 80%;
+        .color-sketch-block-box {
+          width: 100%;
+        }
+        .color-sketch-value {
+          display: none;
+        }
+      }
+    }
+    .mk-color-value {
+      display: inline-block;
+      width: 80%;
+      height: 24px;
+      box-shadow: 0 0 2px #b8b8b8;
+    }
     .ant-select {
       width: 100%;
     }
diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx
index 06635eb..51f9743 100644
--- a/src/components/tabview/index.jsx
+++ b/src/components/tabview/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import { fromJS } from 'immutable'
-import {Tabs, BackTop, notification} from 'antd'
-import { RedoOutlined, CloseOutlined } from '@ant-design/icons'
+import { Tabs, BackTop, notification, Modal } from 'antd'
+import { RedoOutlined, CloseOutlined, LoadingOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import 'moment/locale/zh-cn'
 
@@ -25,8 +25,10 @@
   state = {
     activeId: '',
     tabviews: [],
-    iFrameHeight: 0,
+    visible: false
   }
+
+  reloading = false
 
   UNSAFE_componentWillMount () {
     if (!window.GLOB.mkHS) {
@@ -44,6 +46,10 @@
   componentDidMount () {
     MKEmitter.addListener('modifyTabs', this.modifyTabs)
     MKEmitter.addListener('closeTabView', this.closeTabView)
+
+    if (window.GLOB.forcedUpdate) {
+      MKEmitter.addListener('reloadTabs', this.reloadTabs)
+    }
   }
 
   /**
@@ -54,6 +60,7 @@
       return
     }
     MKEmitter.removeListener('modifyTabs', this.modifyTabs)
+    MKEmitter.removeListener('reloadTabs', this.reloadTabs)
     MKEmitter.removeListener('closeTabView', this.closeTabView)
   }
 
@@ -143,6 +150,53 @@
     } else {
       MKEmitter.emit('reloadMenuView', menu.MenuID)
     }
+  }
+
+  reloadTabs = () => {
+    if (this.reloading) return
+
+    this.reloading = true
+    let time = new Date().getTime()
+
+    this.setState({visible: true})
+
+    Api.getAppVersion(true).then((list) => {
+      let _time = new Date().getTime()
+      let delay = _time - time
+      delay = delay < 3000 ? 3000 - delay : 0
+
+      setTimeout(() => {
+        this.setState({visible: false})
+        this.reloading = false
+  
+        Modal.success({
+          title: '鏇存柊鎴愬姛銆�',
+        })
+  
+        if (list && list.length) {
+          let _tabIds = this.state.tabviews.map(item => item.MenuID)
+          list.forEach((m, i) => {
+            if (_tabIds.includes(m)) {
+              setTimeout(() => {
+                MKEmitter.emit('reloadMenuView', m)
+              }, i * 20)
+            }
+          })
+        }
+      }, delay)
+    }, (message) => {
+      let _time = new Date().getTime()
+      let delay = _time - time
+      delay = delay < 3000 ? 3000 - delay : 0
+
+      setTimeout(() => {
+        this.setState({visible: false})
+        this.reloading = false
+        Modal.error({
+          title: message || '绯荤粺閰嶇疆鏇存柊澶辫触锛�',
+        })
+      }, delay)
+    })
   }
 
   modifyTabs = (tab, fixed) => {
@@ -236,7 +290,7 @@
   }
 
   render () {
-    const { tabviews, activeId } = this.state
+    const { tabviews, activeId, visible } = this.state
 
     return (
       <section id="mk-tabgroup-wrap" className="mk-tabview-wrap">
@@ -273,6 +327,21 @@
             </Tabs>
           }
         </div>
+        <Modal
+          visible={visible}
+          width={400}
+          closable={false}
+          centered={true}
+          footer={null}
+          destroyOnClose
+        >
+          <div className="mk-menus-update">
+            <div className="tip">
+              绯荤粺鏇存柊涓紝璇风◢鍚�
+            </div>
+            <LoadingOutlined />
+          </div>
+        </Modal>
       </section>
     )
   }
diff --git a/src/components/tabview/index.scss b/src/components/tabview/index.scss
index 040e6bf..130fc12 100644
--- a/src/components/tabview/index.scss
+++ b/src/components/tabview/index.scss
@@ -110,4 +110,16 @@
 .ant-message {
   top: 50px;
   z-index: 1080;
+}
+
+.mk-menus-update {
+  text-align: center;
+  font-size: 20px;
+  color: #131313;
+  .tip {
+    margin-bottom: 10px;
+  }
+  .anticon {
+    color: var(--mk-sys-color);
+  }
 }
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 96650ef..caf9ae3 100644
--- a/src/index.js
+++ b/src/index.js
@@ -88,6 +88,13 @@
       GLOB.externalDatabase = null
     }
 
+    if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
+      GLOB.probation = true
+    }
+    if (config.forcedUpdate && /^20\d{2}-\d{2}-\d{2}$/.test(config.forcedUpdate) && new Date(config.forcedUpdate).getTime() > new Date().getTime()) {
+      GLOB.forcedUpdate = true
+    }
+
     // 鍙湁涓氬姟绯荤粺鎵嶅彲浠ヨ缃负姝e紡绯荤粺
     if (GLOB.sysType === 'local' && (config.systemType === 'official' || config.systemType === 'production')) {
       if (!config.mainSystemApi) {
@@ -102,12 +109,6 @@
       }
 
       GLOB.systemType = 'production'
-      if (config.probation && /^20\d{2}-\d{2}-\d{2}$/.test(config.probation) && new Date(config.probation).getTime() > new Date().getTime()) {
-        GLOB.probation = true
-      }
-      if (config.forcedUpdate && /^20\d{2}-\d{2}-\d{2}$/.test(config.forcedUpdate) && new Date(config.forcedUpdate).getTime() > new Date().getTime()) {
-        GLOB.forcedUpdate = true
-      }
     } else if (GLOB.sysType === 'local') {
       GLOB.probation = true
       GLOB.debugger = true
@@ -258,6 +259,11 @@
       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(_href + 'lang') || (config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
     sessionStorage.setItem('lang', lang)
 
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index 4f030d2..516c514 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -283,7 +283,7 @@
           <div className="mk-popover-control">
             <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={this.addElement} />
             <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} />
-            <NormalForm title="娴姩鍗¤缃�" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
+            <NormalForm title="娴姩鍗¤缃�" width={900} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="balcony" card={card}/>
diff --git a/src/menu/components/card/balcony/index.scss b/src/menu/components/card/balcony/index.scss
index 418b226..efe4ce6 100644
--- a/src/menu/components/card/balcony/index.scss
+++ b/src/menu/components/card/balcony/index.scss
@@ -32,7 +32,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-color: #ffffff;
     background-position: center center;
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index cfd50f8..c73bf93 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -113,6 +113,7 @@
         <div>2銆佸悓姝ョ被鍨嬩腑鍏紡銆佹寜閽互鍙婂叏閫夊厓绱犳瘮杈冪壒娈婏紝鎿嶄綔鏁版嵁涓哄叾鍚屾缁勪欢鐨勬暟鎹��</div>
         <div>3銆佷笂绾х被鍨嬮渶娣诲姞褰撳墠缁勪欢鐨勪笂绾х粍浠讹紝骞跺彲璁剧疆褰撳墠缁勪欢涓哄缁堟樉绀猴紝杩樻槸鍙湁鍦ㄤ笂绾х粍浠堕�夎鍚庢墠鏄剧ず銆�</div>
       </div>,
+      toolWidth: 400,
       required: false,
       options: [
         {value: 'static', label: '鐙珛'},
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
index 47cdb5d..4db573b 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/action.jsx
@@ -66,17 +66,17 @@
   } else if (card.show === 'icon') {
     btnElement = (<Button style={_style} type="link"><MkIcon type={card.icon}/>{warning}</Button>)
   } else if (card.show === 'link') {
-    btnElement = (<Button style={_style} type="link">{card.label}{card.icon ? <MkIcon type={card.icon}/> : null}{warning}</Button>)
+    btnElement = (<Button style={_style} type="link">{card.showName || card.label}{card.icon ? <MkIcon type={card.icon}/> : null}{warning}</Button>)
   } else {
-    btnElement = (<Button style={_style}>{card.icon ? <MkIcon type={card.icon}/> : null}{card.label}{warning}</Button>)
+    btnElement = (<Button style={_style}>{card.icon ? <MkIcon type={card.icon}/> : null}{card.showName || card.label}{warning}</Button>)
   }
 
-  let _style_ = null
+  let _style_ = {opacity: isDragging ? 0.3 : 1, ...card.wrapStyle}
 
   if (card.style && card.style.clear === 'left') {
-    _style_ = {clear: 'left'}
+    _style_.clear = 'left'
   } else if (card.style && card.style.clear === 'right') {
-    _style_ = {float: 'right'}
+    _style_.float = 'right'
   }
 
   let className = card.width || 0
@@ -105,9 +105,7 @@
       </div>
     } trigger="hover">
       <div ref={node => drag(drop(node))} style={_style_} className={'ant-col card-button-cell ant-col-' + className} onDoubleClick={(e) => {e.stopPropagation(); doubleClickCard(id)}}>
-        <div style={{opacity: isDragging ? 0.3 : 1, ...card.wrapStyle}}>
-          {btnElement}
-        </div>
+        {btnElement}
       </div>
     </Popover>
   )
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
index 7395d2a..abe02a7 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/card.jsx
@@ -59,7 +59,7 @@
 
   let _style = {opacity: isDragging ? 0.3 : 1}
   
-  if (card.style) {
+  if (card.style && card.eleType !== 'tag') {
     _style = {...card.style, opacity: isDragging ? 0.3 : 1}
     _style = resetStyle(_style)
   }
@@ -184,11 +184,27 @@
         let _s = {fontSize: card.fixSize, color: card.fixColor, marginLeft: card.fixLeft, marginRight: card.fixRight}
         val = <><span style={_s}>{card.prefix || ''}</span>{card.formula}<span style={_s}>{card.postfix || ''}</span></>
       }
+
       return (
         <div className="ant-mk-text" style={{height: card.innerHeight || 'auto'}}>
           {val}
         </div>
       )
+    } else if (card.eleType === 'tag') {
+      let vals = []
+      if (card.datatype === 'static') {
+        vals = card.value.split(',').filter(Boolean)
+      } else {
+        vals = [card.field || '']
+      }
+
+      let _style = resetStyle(card.style)
+
+      return (
+        <div className="ant-mk-tag">
+          {vals.map((val, index) => <span key={index} className="tag-item" style={_style}>{val}</span>)}
+        </div>
+      )
     } else if (card.eleType === 'color') {
       _style.overflow = 'hidden'
       let _bgstyle = {backgroundColor: card.value || '#1890ff'}
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
index 41c2326..207e436 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.jsx
@@ -140,6 +140,18 @@
           if (item.value === 'splitline') {
             newcard.width = 24
             newcard.color = '#EBE9E9'
+          } else if (item.value === 'tag') {
+            newcard.style = {
+              backgroundColor: 'var(--mk-sys-color1)',
+              color: 'var(--mk-sys-color)',
+              borderColor: 'var(--mk-sys-color)',
+              borderWidth: '1px',
+              borderRadius: '4px',
+              paddingLeft: '7px',
+              paddingRight: '7px',
+              marginRight: '8px',
+              marginBottom: '8px',
+            }
           } else if (item.value === 'slider') {
             newcard.width = 24
             newcard.color = '#1890ff'
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index a492bac..289da39 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -4,6 +4,7 @@
     font-style: inherit;
     font-weight: inherit;
     text-decoration: inherit;
+    font-family: inherit;
   }
   .ant-mk-text:not(.line1):not(.line) {
     word-break: break-word;
@@ -93,6 +94,12 @@
     border-left: 0;
     border-right: 0;
   }
+  .ant-mk-tag {
+    .tag-item {
+      display: inline-block;
+      vertical-align: top;
+    }
+  }
   .ant-mk-check {
     white-space: nowrap;
     overflow: hidden;
diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.jsx b/src/menu/components/card/cardcellcomponent/elementform/index.jsx
index 8488fd1..992eff8 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 } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Popover, message, AutoComplete } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import { formRule } from '@/utils/option.js'
@@ -10,7 +10,9 @@
 
 const { TextArea } = Input
 const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
+const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
 const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
+const MKTable = asyncComponent(() => import('@/components/normalform/modalform/mkTable'))
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
 
 const cardTypeOptions = {
@@ -25,8 +27,9 @@
   barcode: ['eleType', 'datatype', 'width', 'barHeight', 'displayValue', 'interval', 'noValue'],
   qrcode: ['eleType', 'datatype', 'width', 'qrWidth', 'color', 'url', 'noValue'],
   currentDate: ['eleType', 'width', 'dateFormat', 'prefix', 'postfix', 'fixStyle'],
-  formula: ['eleType', 'width', 'height', 'prefix', 'postfix', 'eval', 'formula', 'noValue', 'fixStyle', 'alignItems'],
+  formula: ['eleType', 'width', 'height', 'eval', 'formula', 'noValue'],
   color: ['eleType', 'datatype', 'width', 'lenWidRadio', 'noValue', 'copyable'],
+  tag: ['eleType', 'datatype', 'width', 'noValue', 'signs'],
 }
 
 class ElementEditForm extends Component {
@@ -58,7 +61,7 @@
       formlist: formlist.map(item => {
         item.hidden = !_options.includes(item.key)
 
-        if (item.key === 'field' || item.key === 'linkurl' || item.key === 'bgImage' || item.key === 'posterField') {
+        if ((item.key === 'field' || item.key === 'linkurl' || item.key === 'bgImage' || item.key === 'posterField') && item.type === 'select') {
           item.options = []
           
           if (side === 'sub') {
@@ -112,26 +115,39 @@
               })
             })
           }
-        } else if (item.key === 'value' && card.eleType === 'slider') {
-          item.type = 'number'
-          item.label = '鍊�'
         } else if (item.key === 'formula') {
           item.fields = []
 
-          config.columns.forEach(col => {
-            item.fields.push(col.field)
-          })
-          
-          if (config.subColumns) {
-            config.subColumns.forEach(col => {
+          if (side === 'sub') {
+            if (config.subColumns) {
+              config.subColumns.forEach(col => {
+                item.fields.push(col.field)
+              })
+            }
+          } else {
+            config.columns.forEach(col => {
               item.fields.push(col.field)
             })
           }
 
           item.fields = item.fields.join(', ')
-        } else if (item.key === 'value' && card.eleType === 'text') {
-          item.type = 'textarea'
-          item.label = '鍐呭'
+        } else if (item.key === 'value') {
+          item.tooltip = ''
+          if (card.eleType === 'slider') {
+            item.type = 'number'
+            item.label = '鍊�'
+          } else if (card.eleType === 'text') {
+            item.type = 'textarea'
+            item.label = '鍐呭'
+            item.tooltip = '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆丂month@銆丂week@銆丂day@'
+          } else if (card.eleType === 'tag') {
+            item.type = 'textarea'
+            item.label = '鍐呭'
+            item.tooltip = '澶氫釜鍊艰浣跨敤閫楀彿锛堣嫳鏂囷級鍒嗛殧銆�'
+          } else {
+            item.type = 'text'
+            item.label = '鍐呭'
+          }
         } else if (item.key === 'format') {
           if (card.eleType === 'text') {
             item.options = item.oriOptions.filter(op => !['percent', 'thdSeparator', 'abs'].includes(op.value))
@@ -142,7 +158,7 @@
           item.required = card.eleType !== 'qrcode'
         }
         if (item.key === 'linkurl') {
-          item.type = card.link === 'dynamic' ? 'select' : 'textarea'
+          item.type = card.link === 'dynamic' ? item.defType : 'textarea'
         }
 
         return item
@@ -153,7 +169,7 @@
   getOptions = () => {
     let _options = fromJS(cardTypeOptions[this.record.eleType]).toJS() // 閫夐」鍒楄〃
     
-    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color'].includes(this.record.eleType)) {
+    if (['text', 'number', 'picture', 'slider', 'barcode', 'qrcode', 'video', 'color', 'tag'].includes(this.record.eleType)) {
       if (this.record.datatype === 'dynamic') {
         _options.push('field')
         if (this.record.eleType === 'number') {
@@ -178,14 +194,14 @@
       if (['text', 'picture'].includes(this.record.eleType) && this.record.link) {
         _options.push('linkType')
         if (this.record.linkType === 'linkmenu') {
-          _options.push('open', 'joint')
+          _options.push('open')
           if (this.record.link === 'static') {
             _options.push('linkmenu')
           } else {
             _options.push('linkurl')
           }
         } else if (this.record.linkType === 'other') {
-          _options.push('linkurl', 'joint', 'open')
+          _options.push('linkurl', 'open')
         } else {
           _options.push('linkurl')
         }
@@ -210,8 +226,13 @@
       if (this.record.tipType === 'text') {
         _options.push('height')
       }
-    } else if (this.record.eleType === 'formula' && this.record.eval === 'true') {
-      _options.push('decimal')
+    } else if (this.record.eleType === 'formula') {
+      if (this.record.eval !== 'func') {
+        _options.push('prefix', 'postfix', 'fixStyle', 'alignItems')
+      }
+      if (this.record.eval === 'true') {
+        _options.push('decimal')
+      }
     }
     if (_options.includes('fixStyle') && this.record.fixStyle === 'alone') {
       _options.push('fixSize', 'fixColor', 'fixLeft', 'fixRight')
@@ -245,7 +266,7 @@
         item.initVal = this.record[item.key]
         item.hidden = !_options.includes(item.key)
 
-        if (item.key === 'field') {
+        if (item.key === 'field' && item.type === 'select') {
           item.options = []
 
           if (side === 'sub') {
@@ -281,12 +302,18 @@
             })
           }
         } else if (item.key === 'value') {
+          item.tooltip = ''
           if (value === 'slider') {
             item.type = 'number'
             item.label = '鍊�'
           } else if (value === 'text') {
             item.type = 'textarea'
             item.label = '鍐呭'
+            item.tooltip = '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆丂month@銆丂week@銆丂day@'
+          } else if (value === 'tag') {
+            item.type = 'textarea'
+            item.label = '鍐呭'
+            item.tooltip = '澶氫釜鍊艰浣跨敤閫楀彿锛堣嫳鏂囷級鍒嗛殧銆�'
           } else {
             item.type = 'text'
             item.label = '鍐呭'
@@ -339,7 +366,7 @@
           item.hidden = !_options.includes(item.key)
 
           if (item.key === 'linkurl') {
-            item.type = value === 'dynamic' ? 'select' : 'textarea'
+            item.type = value === 'dynamic' ? item.defType : 'textarea'
           }
           return item
         })
@@ -373,106 +400,122 @@
     this.state.formlist.forEach((item, index) => {
       if (item.hidden || item.forbid) return
 
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
+
       if (item.type === 'text') {
+        let rules = item.rules || []
+        if (item.options && item.options.length > 0) {
+          fields.push(
+            <Col span={12} key={index}>
+              <Form.Item label={label}>
+                {getFieldDecorator(item.key, {
+                  initialValue: item.initVal || '',
+                  rules: [
+                    {
+                      required: !!item.required,
+                      message: '璇疯緭鍏�' + item.label + '!'
+                    },
+                    {
+                      pattern: formRule.field.pattern,
+                      message: formRule.field.message
+                    },
+                    {
+                      max: formRule.input.max,
+                      message: formRule.input.message
+                    }
+                  ]
+                })(
+                  <AutoComplete
+                    dataSource={item.options.map((cell, i) => <AutoComplete.Option value={cell.value} key={i}>
+                      {cell.value}
+                    </AutoComplete.Option>)}
+                    filterOption={(input, option) => option.props.children.indexOf(input) > -1}
+                  >
+                    <Input autoComplete="off" onPressEnter={this.handleSubmit} />
+                  </AutoComplete>
+                )}
+              </Form.Item>
+            </Col>
+          )
+        } else {
+          fields.push(
+            <Col span={12} key={index}>
+              <Form.Item label={label}>
+                {getFieldDecorator(item.key, {
+                  initialValue: item.initVal || '',
+                  rules: [
+                    {
+                      required: item.readonly ? false : !!item.required,
+                      message: '璇疯緭鍏�' + item.label + '!'
+                    },
+                    {
+                      max: formRule.input.max,
+                      message: formRule.input.message
+                    },
+                    ...rules
+                  ]
+                })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+          )
+        }
+      } else if (item.type === 'textarea') {
         fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+          <Col span={24} className="textarea" key={index}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
                   {
                     required: item.readonly ? false : !!item.required,
                     message: '璇疯緭鍏�' + item.label + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
+              })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
             </Form.Item>
           </Col>
         )
-      } else if (item.type === 'textarea') {
-        if (item.key === 'formula') {
+      } else if (item.type === 'number') {
+        if (item.help) {
           fields.push(
-            <Col span={24} className="textarea" key={index}>
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+            <Col span={12} key={index}>
+              <Form.Item help={item.help} label={label}>
                 {getFieldDecorator(item.key, {
-                  initialValue: item.initVal || '',
-                  rules: [
-                    {
-                      required: item.readonly ? false : !!item.required,
-                      message: '璇疯緭鍏�' + item.label + '!'
-                    }
-                  ]
-                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+                  initialValue: item.initVal,
+                  rules: [{
+                    required: item.readonly ? false : !!item.required,
+                    message: '璇疯緭鍏�' + item.label + '!'
+                  }]
+                })(<InputNumber min={item.min || 0} max={item.max || 10000} precision={item.precision || 0} onPressEnter={this.handleSubmit} />)}
               </Form.Item>
-              <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
-                <span className="formula-icon">瀛楁闆�</span>
-              </Popover>
             </Col>
           )
         } else {
           fields.push(
-            <Col span={24} className="textarea" key={index}>
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+            <Col span={12} key={index}>
+              <Form.Item label={label}>
                 {getFieldDecorator(item.key, {
-                  initialValue: item.initVal || '',
-                  rules: [
-                    {
-                      required: item.readonly ? false : !!item.required,
-                      message: '璇疯緭鍏�' + item.label + '!'
-                    }
-                  ]
-                })(<TextArea autoSize={{minRows: 2}} disabled={item.readonly} placeholder={item.placeholder || ''} />)}
+                  initialValue: item.initVal,
+                  rules: [{
+                    required: item.readonly ? false : !!item.required,
+                    message: '璇疯緭鍏�' + item.label + '!'
+                  }]
+                })(<InputNumber min={item.min || 0} max={item.max || 10000} precision={item.precision || 0} onPressEnter={this.handleSubmit} />)}
               </Form.Item>
             </Col>
           )
         }
-      } else if (item.type === 'number') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item help={item.help || null} label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [{
-                  required: item.readonly ? false : !!item.required,
-                  message: '璇疯緭鍏�' + item.label + '!'
-                }]
-              })(<InputNumber min={item.min || 0} max={item.max || 10000} precision={item.precision || 0} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
       } else if (item.type === 'select') { // 涓嬫媺鎼滅储
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [{
@@ -500,12 +543,7 @@
       } else if (item.type === 'icon') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [{
@@ -521,12 +559,7 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [{
@@ -548,7 +581,7 @@
       } else if (item.type === 'color') {
         fields.push(
           <Col span={12} key={index} className="color-form">
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -571,12 +604,7 @@
 
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -594,12 +622,7 @@
       } else if (item.type === 'cascader') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || [],
                 rules: [
@@ -612,6 +635,45 @@
                 <Cascader options={item.options || []} expandTrigger="hover" placeholder=""/>
               )}
             </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'table') {
+        fields.push(
+          <Col span={24} key={index} className="textarea">
+            <Form.Item label={label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: '璇疯緭鍏�' + item.label + '!'
+                  }
+                ]
+              })(
+                <MKTable columns={item.columns || []} actions={item.actions}/>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'codemirror') {
+        fields.push(
+          <Col span={24} key={index} className="textarea">
+            <Form.Item label={label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: '璇疯緭鍏�' + item.label + '!'
+                  }
+                ]
+              })(
+                <CodeMirror mode="text/javascript"/>
+              )}
+            </Form.Item>
+            <Popover overlayClassName="formula-fields" placement="topLeft" title="" content={<div>{item.fields}</div>} trigger="click">
+              <span className="formula-icon">瀛楁闆�</span>
+            </Popover>
           </Col>
         )
       }
@@ -648,6 +710,19 @@
             })
           }
 
+          if (values.width === 0) {
+            let utype = {picture: '鍥剧墖', video: '瑙嗛', slider: '杩涘害鏉�', splitline: '鍒嗗壊绾�', barcode: '鏉″舰鐮�', qrcode: '浜岀淮鐮�'}
+            
+            if (utype[values.eleType]) {
+              message.warning(utype[values.eleType] + '鍏冪礌瀹藉害涓嶅彲涓�0锛�')
+              return
+            }
+          }
+          
+          if (values.eleType === 'tag' && values.signs && values.signs.length === 0) {
+            values.signs = null
+          }
+
           resolve(values)
         } else {
           reject(err)
diff --git a/src/menu/components/card/cardcellcomponent/elementform/index.scss b/src/menu/components/card/cardcellcomponent/elementform/index.scss
index aaa2c39..e2aa807 100644
--- a/src/menu/components/card/cardcellcomponent/elementform/index.scss
+++ b/src/menu/components/card/cardcellcomponent/elementform/index.scss
@@ -14,10 +14,13 @@
       .ant-form-item-control-wrapper {
         width: 85.8%;
       }
+      .CodeMirror {
+        height: 200px;
+      }
 
       .formula-icon {
         position: absolute;
-        bottom: 5px;
+        top: -18px;
         right: 15px;
         cursor: pointer;
         font-size: 12px;
@@ -36,6 +39,10 @@
   .ant-form-explain, .ant-form-extra {
     font-size: 13px;
   }
+  .ant-select-search__field__mirror {
+    max-width: 100%;
+    overflow: hidden;
+  }
 }
 .formula-fields {
   z-index: 1200!important;
diff --git a/src/menu/components/card/cardcellcomponent/formconfig.jsx b/src/menu/components/card/cardcellcomponent/formconfig.jsx
index f0464b2..7b651e9 100644
--- a/src/menu/components/card/cardcellcomponent/formconfig.jsx
+++ b/src/menu/components/card/cardcellcomponent/formconfig.jsx
@@ -1,3 +1,4 @@
+import React from 'react'
 import MenuUtils from '@/utils/utils-custom.js'
 
 /**
@@ -20,6 +21,7 @@
     { value: 'qrcode', text: '浜岀淮鐮�'},
     { value: 'currentDate', text: '褰撳墠鏃堕棿'},
     { value: 'formula', text: '鍏紡'},
+    { value: 'tag', text: '鏍囩'},
     { value: 'color', text: '棰滆壊'},
   ]
 
@@ -52,7 +54,7 @@
     _options = [{ value: 'text', text: '鏂囨湰'}]
   }
 
-  let width = card.width || 12
+  let width = card.width === undefined ? 12 : card.width
   if (/x/.test(card.width)) {
     width = +width.replace(/x/, '.5')
   }
@@ -60,6 +62,7 @@
   let linkTypes = [
     { value: 'tel', text: '鐢佃瘽' },
     { value: 'email', text: '閭' },
+    { value: 'linkmenu', text: '鍏宠仈鑿滃崟' },
     { value: 'download', text: '涓嬭浇' },
     { value: 'other', text: '鍏朵粬' }
   ]
@@ -89,13 +92,25 @@
       card.linkType = ''
       card.linkurl = ''
     }
-  } else if (card.linkType === 'linkmenu') {
-    if (appType !== 'mob' && appType !== 'pc') {
-      card.link = ''
-      card.linkType = ''
-      card.linkurl = ''
-      card.linkmenu = ''
+  // } else if (card.linkType === 'linkmenu') {
+  //   if (appType !== 'mob' && appType !== 'pc') {
+  //     card.link = ''
+  //     card.linkType = ''
+  //     card.linkurl = ''
+  //     card.linkmenu = ''
+  //   }
+  }
+
+  let menulist = sessionStorage.getItem('fstMenuList')
+
+  if (appType === '' && menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch (e) {
+      menulist = []
     }
+  } else {
+    menulist = []
   }
 
   let appMenus = sessionStorage.getItem('appMenus')
@@ -110,6 +125,17 @@
       appMenus = []
     }
     appMenus.push({value: 'goback', text: '杩斿洖锛堜笂涓�椤碉級'})
+  }
+
+  let fields = []
+  let isStatic = (cards.subtype === 'propcard' || cards.type === 'balcony') && cards.wrap.datatype === 'static'
+  if (isStatic) {
+    if (cards.wrap.supModule && cards.wrap.supModule.length) {
+      let cell = MenuUtils.getComponent(cards.wrap.supModule[cards.wrap.supModule.length - 1])
+      if (cell && cell.columns) {
+        fields = cell.columns.map(col => ({ value: col.field }))
+      }
+    }
   }
 
   let forms = [
@@ -145,12 +171,17 @@
       ]
     },
     {
-      type: 'select',
+      type: isStatic ? 'text' : 'select',
       key: 'field',
       label: '瀛楁',
       initVal: card.field || '',
+      tooltip: isStatic ? '鍙粦瀹氫笂绾х粍浠跺瓧娈碉紝涓嶅瓨鍦ㄤ笂绾х粍浠舵椂鍙粦瀹歶rl鍙傛暟瀛楁銆�' : '',
       required: true,
-      options: []
+      options: fields,
+      rules: [{
+        pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
+        message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯-'
+      }]
     },
     {
       type: 'icon',
@@ -165,7 +196,7 @@
       min: 0,
       label: '鍐呭',
       initVal: card.value || '',
-      tooltip: '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆丂month@銆丂week@銆丂day@',
+      // tooltip: '鏂囨湰绫诲瀷锛屼細鏇挎崲鍐呭涓殑@username@銆丂fullName@銆丂mk_city@銆丂appname@銆丂bid@銆丂month@銆丂week@銆丂day@',
       required: true
     },
     {
@@ -229,11 +260,12 @@
       required: true
     },
     {
-      type: 'select',
+      type: isStatic ? 'text' : 'select',
       key: 'posterField',
       label: '棰勮鍦板潃',
       initVal: card.posterField || '',
-      required: true
+      required: true,
+      options: fields
     },
     {
       type: 'radio',
@@ -301,6 +333,7 @@
         { value: 'YYYY-MM', text: 'YYYY-MM' },
         { value: 'YYYY-MM-DD HH:mm', text: 'YYYY-MM-DD HH:mm' },
         { value: 'YYYY-MM-DD HH:mm:ss', text: 'YYYY-MM-DD HH:mm:ss' },
+        { value: 'YYYY骞碝M鏈圖D鏃�', text: 'YYYY骞碝M鏈圖D鏃�' },
       ]
     },
     {
@@ -427,12 +460,12 @@
     {
       type: 'number',
       key: 'width',
-      min: 0.5,
+      min: 0,
       max: 24,
       precision: 1,
       label: '鍏冪礌瀹藉害',
       initVal: width,
-      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒楋紝鍙缃崐鍒楀嵆.5銆�',
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒楋紝鍙缃崐鍒楀嵆.5銆傛敞锛氫负0鏃跺搴︿緷鎹唴瀹硅嚜閫傚簲锛堟枃鏈�佹暟鍊笺�佹彁绀猴紙鍥炬爣锛夈�佸綋鍓嶆椂闂淬�佸叕寮忥級銆�',
       required: true
     },
     {
@@ -446,14 +479,14 @@
       required: false
     },
     {
-      type: 'select',
+      type: isStatic ? 'text' : 'select',
       key: 'bgImage',
       label: '鍔ㄦ�佽儗鏅�',
       initVal: card.bgImage || '',
       tooltip: '缁戝畾鏁版嵁婧愬瓧娈碉紝鍙牴鎹繑鍥炲�兼敼鍙樿儗鏅浘銆�',
       required: false,
       allowClear: true,
-      options: [],
+      options: fields,
       forbid: isHeader
     },
     {
@@ -579,7 +612,7 @@
       key: 'link',
       label: '閾炬帴',
       initVal: card.link || '',
-      tooltip: '鍔ㄦ�佸湴鍧�涓虹粦瀹氬瓧娈靛�笺��',
+      tooltip: '鍔ㄦ�佸湴鍧�涓虹粦瀹氬瓧娈靛�笺�備娇鐢� 鍔ㄦ��-鍏宠仈鑿滃崟 鏃讹紝璇峰湪鈥滈摼鎺ュ湴鍧�鈥濆瓧娈佃繑鍥炶彍鍗旾D銆�',
       required: false,
       options: [
         { value: '', text: '鏃�' },
@@ -589,7 +622,7 @@
       forbid: isHeader
     },
     {
-      type: linkTypes.length > 4 ? 'select' : 'radio',
+      type: 'select',
       key: 'linkType',
       label: '閾炬帴绫诲瀷',
       initVal: card.linkType || 'other',
@@ -612,18 +645,31 @@
       key: 'linkmenu',
       label: '鍏宠仈鑿滃崟',
       initVal: card.linkmenu || '',
+      tooltip: '琛屼俊鎭紙瀛楁闆嗕腑鍓�40涓暱搴︿笉瓒呰繃256鐨勫瓧娈碉級灏嗕紶閫掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ��',
       required: true,
       options: appMenus || [],
       forbid: !['pc', 'mob'].includes(appType)
     },
     {
-      type: 'select',
+      type: 'cascader',
+      key: 'linkmenu',
+      label: '鍏宠仈鑿滃崟',
+      initVal: card.linkmenu || [],
+      tooltip: '琛屼俊鎭皢浼犻�掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ��',
+      required: true,
+      options: menulist,
+      forbid: ['pc', 'mob'].includes(appType)
+    },
+    {
+      type: isStatic ? 'text' : 'select',
+      defType: isStatic ? 'text' : 'select',
       key: 'linkurl',
       label: '閾炬帴鍦板潃',
       initVal: card.linkurl || '',
-      tooltip: ['pc', 'mob'].includes(appType) ? '褰撻摼鎺ョ被鍨嬩负鈥滃叾浠栤�濓紝涓旈摼鎺ュ湴鍧�浠menuid@寮�澶存椂锛屽叾鍚庡唴瀹瑰皢琚涓鸿彍鍗旾D銆�' : '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�' + (['pc', 'mob'].includes(appType) ? '褰撻摼鎺ョ被鍨嬩负鈥滃叾浠栤�濓紝涓旈摼鎺ュ湴鍧�浠menuid@寮�澶存椂锛屽叾鍚庡唴瀹瑰皢琚涓鸿彍鍗旾D銆�' : ''),
+      toolWidth: 350,
       required: true,
-      options: []
+      options: fields
     },
     {
       type: 'radio',
@@ -639,25 +685,12 @@
       ]
     },
     {
-      type: 'radio',
-      key: 'joint',
-      label: '鎷兼帴鍙傛暟',
-      initVal: card.joint || 'true',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
-    },
-    {
-      type: 'textarea',
+      type: 'codemirror',
       key: 'formula',
       label: '鍏紡',
       initVal: card.formula || '',
-      tooltip: '鎵ц鏃朵細浣跨敤鏌ヨ鍒扮殑鏁版嵁鏇挎崲鐩稿簲鐨勫瓧娈碉紝灞曠ず鑾峰緱鐨勭粨鏋滐紝鍦ㄤ笉浣跨敤瑙f瀽鏃舵崲琛岀鎴栫┖鏍间細鏇挎崲涓洪〉闈㈠厓绱犮�傚彲浣跨敤JS鐨勪竴浜涜娉曪紝濡傦細涓夊厓琛ㄨ揪寮� @field1@ > @field2@ ? 0 : 1锛汳ath瀵硅薄锛屽彇缁濆鍊� Math.abs(@field@)銆佸洓鑸嶄簲鍏� Math.round(@field@)绛�',
+      tooltip: '鎵ц鏃朵細浣跨敤鏌ヨ鍒扮殑鏁版嵁鏇挎崲鐩稿簲鐨勫瓧娈碉紝灞曠ず鑾峰緱鐨勭粨鏋滐紝鍦ㄤ笉浣跨敤瑙f瀽鏃舵崲琛岀鎴栫┖鏍间細鏇挎崲涓洪〉闈㈠厓绱犮�傚彲浣跨敤JS鐨勪竴浜涜娉曪紝濡傦細涓夊厓琛ㄨ揪寮� @field1@ > @field2@ ? 0 : 1锛汳ath瀵硅薄锛屽彇缁濆鍊� Math.abs(@field@)銆佸洓鑸嶄簲鍏� Math.round(@field@)绛夈�傛敞锛氫細鏇挎崲鍏紡涓殑@username@銆丂fullName@銆丂bid@銆�',
+      toolWidth: 450,
       placeholder: '渚嬪锛欯price@ * @number@',
       required: true
     },
@@ -773,6 +806,56 @@
       options: [],
       forbid: !isHeader
     },
+    {
+      type: 'table',
+      key: 'signs',
+      label: '鏍囪',
+      initVal: card.signs || [],
+      tooltip: '鍙緷鎹爣绛惧唴瀹硅缃笉鍚屾牱寮忋��',
+      required: false,
+      actions: ['edit', 'del', 'add', 'move'],
+      columns: [
+        {
+          title: '鍊�',
+          dataIndex: 'value',
+          inputType: 'text',
+          editable: true,
+          required: true,
+          unique: true,
+          width: '20%'
+        },
+        {
+          title: '鑳屾櫙',
+          dataIndex: 'background',
+          inputType: 'color',
+          className: 'mini-color',
+          editable: true,
+          required: true,
+          width: '20%',
+          render: (text) => <span className="mk-color-value" style={{background: text}}></span>,
+        },
+        {
+          title: '鏂囧瓧',
+          dataIndex: 'color',
+          inputType: 'color',
+          className: 'mini-color',
+          editable: true,
+          required: true,
+          width: '20%',
+          render: (text) => <span className="mk-color-value" style={{background: text}}></span>,
+        },
+        {
+          title: '杈规',
+          dataIndex: 'border',
+          inputType: 'color',
+          className: 'mini-color',
+          editable: true,
+          required: true,
+          width: '20%',
+          render: (text) => <span className="mk-color-value" style={{background: text}}></span>,
+        },
+      ]
+    },
   ]
 
   return forms
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index b58ca78..50386cc 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -24,11 +24,12 @@
 
 class CardCellComponent extends Component {
   static propTpyes = {
-    cards: PropTypes.object,         // 鑿滃崟閰嶇疆淇℃伅
+    cards: PropTypes.object,
     cardCell: PropTypes.object,
     side: PropTypes.string,
-    elements: PropTypes.array,       // 鍏冪礌闆�
-    updateElement: PropTypes.func    // 鑿滃崟閰嶇疆鏇存柊
+    timestamp: PropTypes.any,
+    elements: PropTypes.array,
+    updateElement: PropTypes.func
   }
 
   state = {
@@ -74,7 +75,7 @@
   }
 
   UNSAFE_componentWillReceiveProps(nextProps) {
-    if (this.props.side !== nextProps.side && nextProps.side) {
+    if (this.props.timestamp !== nextProps.timestamp && nextProps.timestamp) {
       this.setState({
         elements: fromJS(nextProps.elements).toJS()
       })
@@ -150,9 +151,13 @@
       } else {
         options.push('width', 'minHeight', 'float')
         _style.minHeight = _style.minHeight || '28px'
+        _style.textAlign = _style.textAlign || 'center'
       }
+
       if (element.wrapStyle) {
         _style.float = element.wrapStyle.textAlign || 'left'
+      } else {
+        _style.float = _style.float || 'center'
       }
     } else if (element.eleType === 'picture') {
       options = ['background', 'border', 'margin']
@@ -168,8 +173,12 @@
     } else if (element.eleType === 'splitline') {
       options = ['padding', 'margin']
     }
+    if (['text', 'number', 'formula', 'currentDate'].includes(element.eleType)) {
+      options.push('fontFamily')
+      _style.fontFamily = _style.fontFamily ? _style.fontFamily.split(',') : []
+    }
 
-    if (element.eleType !== 'button') {
+    if (element.eleType !== 'button' && element.eleType !== 'tag') {
       options.push('position')
     }
 
@@ -203,8 +212,16 @@
     let _card = fromJS(card).toJS()
 
     if (['text', 'number', 'formula', 'currentDate', 'sequence', 'icon'].includes(_card.eleType)) {
-      _card.style = style
+      _card.style = fromJS(style).toJS()
       let line = _card.height || null
+
+      if (style.fontFamily) {
+        if (style.fontFamily.length === 0) {
+          delete _card.style.fontFamily
+        } else {
+          _card.style.fontFamily = style.fontFamily.join(',')
+        }
+      }
 
       if (['currentDate', 'sequence'].includes(_card.eleType) || (_card.eleType === 'icon' && _card.tipType !== 'text')) {
         line = 1
@@ -238,9 +255,17 @@
     } else if (_card.eleType === 'button') { // 鎷嗗垎style
       _card.style = fromJS(style).toJS()
 
-      if (style.float) {
+      if (style.float === 'center') {
+        delete _card.style.float
+      } else 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
       }
     } else if (_card.eleType === 'picture') {
       _card.style = style
@@ -322,7 +347,7 @@
       this.setState({
         actvisible: true,
         card: card,
-        formlist: getBaseTableActionForm(card, functip, cards, usefulFields, modules)
+        formlist: getBaseTableActionForm(card, functip, cards, usefulFields, modules, 'line')
       })
     } else {
       let anchors = MenuUtils.getAnchors(menu.components, cards.uuid) || []
@@ -330,7 +355,7 @@
       this.setState({
         actvisible: true,
         card: card,
-        formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors, side)
+        formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors, side, 'line')
       })
     }
   }
@@ -379,6 +404,9 @@
           if (!['text', 'number', 'icon'].includes(res.eleType)) {
             delete res.style.display
           }
+          if (!['text', 'number', 'formula', 'currentDate'].includes(res.eleType)) {
+            delete res.style.fontFamily
+          }
           
           if (res.eleType === 'splitline' && (cell.eleType !== 'splitline' || cell.focus)) {
             res.style.paddingTop = '5px'
@@ -423,6 +451,21 @@
             delete res.style.paddingBottom
             delete res.style.paddingLeft
             delete res.style.paddingRight
+          } else if (res.eleType === 'tag') {
+            delete res.style.position
+            if (cell.eleType !== 'tag') {
+              res.style = {
+                backgroundColor: 'var(--mk-sys-color1)',
+                color: 'var(--mk-sys-color)',
+                borderColor: 'var(--mk-sys-color)',
+                borderWidth: '1px',
+                borderRadius: '4px',
+                paddingLeft: '7px',
+                paddingRight: '7px',
+                marginRight: '8px',
+                marginBottom: '8px',
+              }
+            }
           }
           
           return res
@@ -447,6 +490,13 @@
     let color = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#666666', default: 'rgba(0, 0, 0, 0.65)' }
 
     this.actionFormRef.handleConfirm().then(res => {
+      if (res.width % 0.5) {
+        res.width = parseInt(res.width / 0.5) * 0.5
+      }
+      if (res.width % 1) {
+        res.width = (res.width + '').replace(/.5/, 'x')
+      }
+      
       let _elements = elements.map(cell => {
         if (cell.uuid === res.uuid) {
           res.eleType = cell.eleType || null
@@ -457,7 +507,8 @@
             if (cell.OpenType !== 'form') {
               res.style = {}
             }
-          } else if (res.class !== cell.class || res.show !== cell.show || !res.style) {
+          // } else if (res.class !== cell.class || res.show !== cell.show || !res.style) {
+          } else if (res.class !== cell.class || !res.style) {
             if (res.class) {
               let cl = res.class.replace('border-', '')
               let style = {}
diff --git a/src/menu/components/card/cardcellcomponent/index.scss b/src/menu/components/card/cardcellcomponent/index.scss
index c8d9688..7006456 100644
--- a/src/menu/components/card/cardcellcomponent/index.scss
+++ b/src/menu/components/card/cardcellcomponent/index.scss
@@ -9,6 +9,7 @@
 
   .card-button-cell {
     float: left;
+    text-align: center;
     button {
       box-shadow: none;
     }
@@ -18,7 +19,7 @@
       background-position: center center;
       height: auto;
       min-height: 28px;
-      text-align: center;
+      text-align: inherit;
       border-width: 0;
       padding: 0;
       overflow: hidden;
@@ -40,6 +41,10 @@
       border-radius: 15px;
     }
   }
+  .card-cell.ant-col-0 {
+    display: block;
+    float: left;
+  }
   .card-cell:hover, .card-button-cell:hover {
     box-shadow: 0px 0px 2px #1890ff;
   }
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index fec3526..823a4b6 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -33,6 +33,7 @@
     formlist: null,        // 璁剧疆琛ㄥ崟淇℃伅
     elements: null,        // 缂栬緫缁�
     side: 'front',
+    timestamp: '',
     appType: sessionStorage.getItem('appType'),
     visible: false
   }
@@ -44,6 +45,7 @@
     const { card } = this.props
 
     this.setState({
+      timestamp: new Date().getTime() + '',
       card: fromJS(card).toJS(),
       elements: fromJS(card.elements).toJS(),
     })
@@ -117,7 +119,7 @@
       _elements = fromJS(card.backElements).toJS()
     }
 
-    this.setState({side: _side, elements: _elements})
+    this.setState({side: _side, elements: _elements, timestamp: new Date().getTime() + ''})
   }
   
   addElement = () => {
@@ -215,9 +217,7 @@
           okText: '纭畾',
           cancelText: '鍙栨秷',
           onOk() {
-            that.setState({ card: _card, side: '', elements: fromJS(_card.elements).toJS() }, () => {
-              that.setState({ side: 'front' })
-            })
+            that.setState({ card: _card, side: 'front', timestamp: new Date().getTime() + '', elements: fromJS(_card.elements).toJS() })
             that.props.updateElement(_card)
           },
           onCancel() {}
@@ -267,6 +267,7 @@
     if (side === 'back' && res.type === 'simple') {
       this.setState({
         side: 'front',
+        timestamp: new Date().getTime() + '',
         elements: fromJS(_card.elements).toJS()
       })
     }
@@ -274,8 +275,121 @@
     this.props.updateElement(_card)
   }
 
+  updateFields = (elements, resolve, type) => {
+    const { card, side } = this.state
+
+    let items = elements
+
+    if (type === 'form') {
+      items = []
+
+      elements.forEach(item => {
+        let cell = {
+          uuid: Utils.getuuid(),
+          eleType: 'text',
+          height: 1,
+          innerHeight: 21,
+          prefix: item.label ? item.label + ': ' : '',
+          datatype: item.field ? 'dynamic' : 'static',
+          field: item.field || '',
+          width: item.span || 12,
+          value: '',
+          style: {marginBottom: '15px'}
+        }
+
+        if (item.type === 'number') {
+          cell.eleType = 'number'
+          cell.decimal = typeof(item.decimal) === 'number' ? item.decimal : ''
+        }
+
+        items.push(cell)
+      })
+    }
+
+    if (items.length === 0) {
+      resolve({status: false, message: '鍏冪礌涓嶅彲涓虹┖锛�'})
+      return
+    }
+
+    let _card = { ...card }
+    let _card2 = { ...card }
+    let pass = false
+
+    if (side === 'back') {
+      if (!_card.backElements || _card.backElements.length === 0) {
+        _card.backElements = items
+        pass = true
+      } else {
+        _card.backElements = items
+        _card2.backElements = [...card.backElements, ...items]
+      }
+    } else {
+      if (!_card.elements || _card.elements.length === 0) {
+        _card.elements = items
+        pass = true
+      } else {
+        _card.elements = items
+        _card2.elements = [...card.elements, ...items]
+      }
+    }
+
+    if (pass) {
+      this.setState({
+        card: _card,
+        timestamp: new Date().getTime() + '',
+        elements: side === 'back' ? fromJS(_card.backElements).toJS() : fromJS(_card.elements).toJS()
+      })
+
+      this.props.updateElement(_card)
+    } else {
+      const that = this
+      const _modal = confirm({
+        title: '鍗$墖涓凡瀛樺湪鍏冪礌锛岃閫夋嫨瑕佽繘琛岀殑鎿嶄綔銆�',
+        className: 'mk-confirm-modal',
+        content: <div className="footer">
+          <Button key="cancel" onClick={() => _modal.destroy()}>鍙栨秷</Button>
+          <Button key="replace" className="mk-border-purple" onClick={() => {
+            that.setState({
+              card: _card,
+              timestamp: new Date().getTime() + '',
+              elements: side === 'back' ? fromJS(_card.backElements).toJS() : fromJS(_card.elements).toJS()
+            })
+      
+            that.props.updateElement(_card)
+            _modal.destroy()
+          }}>鏇挎崲</Button>
+          <Button key="confirm" className="mk-border-green" onClick={() => {
+            that.setState({
+              card: _card2,
+              timestamp: new Date().getTime() + '',
+              elements: side === 'back' ? fromJS(_card2.backElements).toJS() : fromJS(_card2.elements).toJS()
+            })
+      
+            that.props.updateElement(_card2)
+            _modal.destroy()
+          }}>娣诲姞</Button>
+        </div>
+      })
+    }
+
+    resolve({status: true})
+  }
+
   paste = (element, resolve) => {
     const { card } = this.state
+
+    if (['simpleform', 'forms', 'formgroup', 'cardcell'].includes(element.copyType)) {
+      if (element.copyType === 'simpleform') {
+        this.updateFields(element.subcards[0].fields, resolve, 'form')
+      } else if (element.copyType === 'forms') {
+        this.updateFields(element.fields, resolve, 'form')
+      } else if (element.copyType === 'formgroup') {
+        this.updateFields(element.fields, resolve, 'form')
+      } else {
+        this.updateFields(element.elements, resolve)
+      }
+      return
+    }
 
     let _uuid = Utils.getuuid()
     
@@ -343,7 +457,7 @@
 
   render() {
     const { cards } = this.props
-    const { card, elements, side, visible } = this.state
+    const { card, elements, side, visible, timestamp } = this.state
 
     let _style = {...card.style}
 
@@ -390,7 +504,7 @@
       <Col span={card.setting.width || 6} style={_style_}>
         <div className={'card-item ' + (card.setting.btnControl || '') + checkAll + tablerole} style={_style} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard()}} id={card.uuid}>
           <span className="circle-select"></span>
-          <CardCellComponent cards={cards} cardCell={card} side={side} elements={elements} updateElement={this.updateCard}/>
+          <CardCellComponent cards={cards} cardCell={card} side={side} timestamp={timestamp} elements={elements} updateElement={this.updateCard}/>
           <div className="card-control" onDoubleClick={(e) => e.stopPropagation()}>
             <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
               <div className="mk-popover-control">
@@ -400,7 +514,7 @@
                   <EditOutlined className="edit" title="缂栬緫"/>
                 </NormalForm>
                 <CopyComponent type="cardcell" card={card}/>
-                <PasteController options={['action', 'customCardElement']} updateConfig={this.paste} />
+                <PasteController options={['action', 'customCardElement', 'simpleform', 'forms', 'formgroup', 'cardcell']} updateConfig={this.paste} />
                 <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
                 <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
                   <div className="mk-popover-control">
diff --git a/src/menu/components/card/cardcomponent/index.scss b/src/menu/components/card/cardcomponent/index.scss
index 35933f8..fd413e5 100644
--- a/src/menu/components/card/cardcomponent/index.scss
+++ b/src/menu/components/card/cardcomponent/index.scss
@@ -99,3 +99,16 @@
     display: inline;
   }
 }
+
+.mk-confirm-modal {
+  .ant-modal-confirm-btns {
+    display: none;
+  }
+  .footer {
+    margin-top: 24px;
+    text-align: right;
+    .ant-btn {
+      margin-left: 8px;
+    }
+  }
+}
diff --git a/src/menu/components/card/cardcomponent/options.jsx b/src/menu/components/card/cardcomponent/options.jsx
index e4f29d3..28d5b82 100644
--- a/src/menu/components/card/cardcomponent/options.jsx
+++ b/src/menu/components/card/cardcomponent/options.jsx
@@ -149,7 +149,7 @@
         {field: 'menu', values: ['menu']},
         {field: 'linkurl', values: ['link']},
         {field: 'open', values: ['menu', 'link', 'menus']},
-        {field: 'joint', values: ['menu', 'link', 'menus', 'miniprogram']},
+        {field: 'joint', values: ['miniprogram']},
         {field: 'linkbtn', values: ['button']},
         {field: 'clickType', values: ['button']},
         {field: 'menuType', values: ['menus']},
@@ -171,6 +171,7 @@
       field: 'menu',
       label: '鍏宠仈鑿滃崟',
       initval: setting.menu || (appType ? '' : []),
+      tooltip: `琛屼俊鎭�${appType ? '锛堝瓧娈甸泦涓墠40涓暱搴︿笉瓒呰繃256鐨勫瓧娈碉級' : ''}灏嗕紶閫掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ�俙,
       required: true,
       extendName: 'MenuNo',
       options: menulist,
@@ -180,6 +181,8 @@
       field: 'linkurl',
       label: '閾炬帴',
       initval: setting.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true,
       options: [],
       span: 24
diff --git a/src/menu/components/card/cardsimplecomponent/index.jsx b/src/menu/components/card/cardsimplecomponent/index.jsx
index 2eb816e..d7d2fe6 100644
--- a/src/menu/components/card/cardsimplecomponent/index.jsx
+++ b/src/menu/components/card/cardsimplecomponent/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Popover } from 'antd'
+import { Popover, Modal, Button } from 'antd'
 import { PlusOutlined, PlusSquareOutlined, EditOutlined, ArrowLeftOutlined, ArrowRightOutlined, SwapOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -11,6 +11,8 @@
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
+
+const { confirm } = Modal
 
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const NodesWrap = asyncComponent(() => import('./node-wrap'))
@@ -30,7 +32,8 @@
   state = {
     card: null,            // 鍗$墖淇℃伅
     formlist: null,        // 璁剧疆琛ㄥ崟淇℃伅
-    appType: sessionStorage.getItem('appType')
+    appType: sessionStorage.getItem('appType'),
+    timestamp: ''
   }
 
   /**
@@ -40,7 +43,8 @@
     const { card } = this.props
 
     this.setState({
-      card: fromJS(card).toJS()
+      card: fromJS(card).toJS(),
+      timestamp: new Date().getTime() + ''
     })
   }
 
@@ -187,8 +191,99 @@
     this.props.updateElement(_card)
   }
 
+  updateFields = (elements, resolve, type) => {
+    const { card } = this.state
+
+    let items = elements
+
+    if (type === 'form') {
+      items = []
+
+      elements.forEach(item => {
+        let cell = {
+          uuid: Utils.getuuid(),
+          eleType: 'text',
+          height: 1,
+          innerHeight: 21,
+          prefix: item.label ? item.label + ': ' : '',
+          datatype: item.field ? 'dynamic' : 'static',
+          field: item.field || '',
+          width: item.span || 12,
+          value: '',
+          style: {marginBottom: '15px'}
+        }
+
+        if (item.type === 'number') {
+          cell.eleType = 'number'
+          cell.decimal = typeof(item.decimal) === 'number' ? item.decimal : ''
+        }
+
+        items.push(cell)
+      })
+    }
+
+    if (items.length === 0) {
+      resolve({status: false, message: '鍏冪礌涓嶅彲涓虹┖锛�'})
+      return
+    }
+
+    let _card = { ...card, elements: items }
+    let _card2 = { ...card, elements: [...card.elements, ...items] }
+
+    if (card.elements.length === 0) {
+      this.setState({
+        card: _card,
+        timestamp: new Date().getTime() + ''
+      })
+
+      this.props.updateElement(_card)
+    } else {
+      const that = this
+      const _modal = confirm({
+        title: '鍗$墖涓凡瀛樺湪鍏冪礌锛岃閫夋嫨瑕佽繘琛岀殑鎿嶄綔銆�',
+        className: 'mk-confirm-modal',
+        content: <div className="footer">
+          <Button key="cancel" onClick={() => _modal.destroy()}>鍙栨秷</Button>
+          <Button key="replace" className="mk-border-purple" onClick={() => {
+            that.setState({
+              card: _card,
+              timestamp: new Date().getTime() + ''
+            })
+      
+            that.props.updateElement(_card)
+            _modal.destroy()
+          }}>鏇挎崲</Button>
+          <Button key="confirm" className="mk-border-green" onClick={() => {
+            that.setState({
+              card: _card2,
+              timestamp: new Date().getTime() + ''
+            })
+      
+            that.props.updateElement(_card2)
+            _modal.destroy()
+          }}>娣诲姞</Button>
+        </div>
+      })
+    }
+
+    resolve({status: true})
+  }
+
   paste = (element, resolve) => {
     const { card } = this.state
+
+    if (['simpleform', 'forms', 'formgroup', 'cardcell'].includes(element.copyType)) {
+      if (element.copyType === 'simpleform') {
+        this.updateFields(element.subcards[0].fields, resolve, 'form')
+      } else if (element.copyType === 'forms') {
+        this.updateFields(element.fields, resolve, 'form')
+      } else if (element.copyType === 'formgroup') {
+        this.updateFields(element.fields, resolve, 'form')
+      } else {
+        this.updateFields(element.elements, resolve)
+      }
+      return
+    }
 
     let _uuid = Utils.getuuid()
     
@@ -208,7 +303,7 @@
 
   render() {
     const { cards } = this.props
-    const { card } = this.state
+    const { card, timestamp } = this.state
 
     let _style = {...card.style}
 
@@ -225,7 +320,7 @@
 
     return (
       <div className="card-item" style={_style}>
-        <CardCellComponent cards={cards} cardCell={card} elements={card.elements} updateElement={this.updateCard}/>
+        <CardCellComponent cards={cards} cardCell={card} timestamp={timestamp} elements={card.elements} updateElement={this.updateCard}/>
         <div className="card-control">
           <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
             <div className="mk-popover-control">
@@ -235,7 +330,7 @@
                 <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
               </NormalForm> : <NodesWrap card={card} updateMenus={this.updateNodes}/>}
               {cards.type !== 'timeline' ? <CopyComponent type="cardcell" card={card}/> : null}
-              <PasteController options={['action', 'customCardElement']} updateConfig={this.paste} />
+              <PasteController options={['action', 'customCardElement', 'simpleform', 'forms', 'formgroup', 'cardcell']} updateConfig={this.paste} />
               <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
               {control ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
                 <div className="mk-popover-control">
diff --git a/src/menu/components/card/cardsimplecomponent/index.scss b/src/menu/components/card/cardsimplecomponent/index.scss
index 0f6054d..a41bcf9 100644
--- a/src/menu/components/card/cardsimplecomponent/index.scss
+++ b/src/menu/components/card/cardsimplecomponent/index.scss
@@ -12,4 +12,17 @@
     cursor: pointer;
     background: rgba(255, 255, 255, 0.55);
   }
+}
+
+.mk-confirm-modal {
+  .ant-modal-confirm-btns {
+    display: none;
+  }
+  .footer {
+    margin-top: 24px;
+    text-align: right;
+    .ant-btn {
+      margin-left: 8px;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/menu/components/card/cardsimplecomponent/options.jsx b/src/menu/components/card/cardsimplecomponent/options.jsx
index f6ca23b..b23531a 100644
--- a/src/menu/components/card/cardsimplecomponent/options.jsx
+++ b/src/menu/components/card/cardsimplecomponent/options.jsx
@@ -38,16 +38,18 @@
       field: 'condition',
       label: '鏄剧ず鏉′欢',
       initval: setting.condition || 'false',
-      tooltip: '褰撻�夋嫨鈥滄湁鈥濇椂锛屽彧鏈夌鍚堟潯浠剁殑鏁版嵁鎵嶄細灞曠ず銆�',
+      tooltip: '褰撻�夋嫨鈥滆嚜瀹氫箟鈥濇椂锛屽彧鏈夌鍚堟潯浠剁殑鏁版嵁鎵嶄細灞曠ず銆傚綋閫夋嫨鈥滄爣棰樷�濇椂锛屽彧鏈夐琛屾墠浼氬睍绀�',
       required: false,
       options: [
-        {value: 'true', label: '鏈�'},
-        {value: 'false', label: '鏃�'},
+        {value: 'false', label: '濮嬬粓鏄剧ず'},
+        {value: 'true', label: '鑷畾涔�'},
+        {value: 'title', label: '鏍囬'},
       ],
       controlFields: [
         {field: 'controlField', values: ['true']},
         {field: 'controlType', values: ['true']},
         {field: 'controlValue', values: ['true']},
+        {field: 'click', values: ['true', 'false']},
       ]
     },
     {
@@ -95,20 +97,8 @@
         {field: 'menu', values: ['menu']},
         {field: 'linkurl', values: ['link']},
         {field: 'open', values: ['menu', 'link']},
-        {field: 'joint', values: ['menu', 'link']},
         {field: 'linkbtn', values: ['button']},
       ]
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: setting.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
     },
     {
       type: 'radio',
@@ -127,6 +117,7 @@
       field: 'menu',
       label: '鍏宠仈鑿滃崟',
       initval: setting.menu || (appType ? '' : []),
+      tooltip: `琛屼俊鎭�${appType ? '锛堝瓧娈甸泦涓墠40涓暱搴︿笉瓒呰繃256鐨勫瓧娈碉級' : ''}灏嗕紶閫掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ�俙,
       required: true,
       extendName: 'MenuNo',
       options: appType ? appmenulist : menulist,
@@ -136,6 +127,8 @@
       field: 'linkurl',
       label: '閾炬帴',
       initval: setting.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true,
       options: [],
       span: 24
@@ -243,7 +236,7 @@
         {field: 'menu', values: ['menu']},
         {field: 'linkurl', values: ['link']},
         {field: 'open', values: ['menu', 'link']},
-        {field: 'joint', values: ['menu', 'link', 'miniprogram']},
+        {field: 'joint', values: ['miniprogram']},
         {field: 'miniAppId', values: ['miniprogram']},
         {field: 'miniPath', values: ['miniprogram']},
       ]
@@ -253,6 +246,7 @@
       field: 'menu',
       label: '鍏宠仈鑿滃崟',
       initval: setting.menu || (appType ? '' : []),
+      tooltip: `琛屼俊鎭�${appType ? '锛堝瓧娈甸泦涓墠40涓暱搴︿笉瓒呰繃256鐨勫瓧娈碉級' : ''}灏嗕紶閫掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ�俙,
       required: true,
       extendName: 'MenuNo',
       options: appType ? appmenulist : menulist,
@@ -300,6 +294,8 @@
       field: 'linkurl',
       label: '閾炬帴',
       initval: setting.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true,
       options: [],
       span: 24
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index b16fec5..7bb0284 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -370,6 +370,19 @@
   updateWrap = (res) => {
     const { card } = this.state
 
+    if (res.interaction) {
+      if (res.interaction.includes('scale')) {
+        res.scale = 'true'
+      }
+      if (res.interaction.includes('parity')) {
+        res.parity = 'true'
+      }
+      if (res.interaction.includes('hover')) {
+        res.hover = 'true'
+      }
+      delete res.interaction
+    }
+
     let _card = {...card, wrap: res}
 
     if (res.supNodes) {
@@ -538,7 +551,7 @@
             <PlusOutlined className="plus" title="娣诲姞鍗$墖" onClick={() => this.addCard()}/>
             {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="娣诲姞鎼滅储" onClick={() => this.addSearch()}/> : null}
             <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.addButton()}/>
-            <NormalForm title="鏁版嵁鍗¤缃�" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+            <NormalForm title="鏁版嵁鍗¤缃�" width={850} update={this.updateWrap} getForms={this.getWrapForms}>
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="datacard" card={card}/>
diff --git a/src/menu/components/card/data-card/index.scss b/src/menu/components/card/data-card/index.scss
index 8c298e3..43ac9dc 100644
--- a/src/menu/components/card/data-card/index.scss
+++ b/src/menu/components/card/data-card/index.scss
@@ -20,7 +20,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-color: #ffffff;
     background-position: center center;
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index 22cd055..91f71f7 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -59,6 +59,74 @@
     }
   }
 
+  let interaction = []
+  let interOptions = []
+
+  if (wrap.scale === 'true') {
+    interaction.push('scale')
+  }
+  if (wrap.parity === 'true') {
+    interaction.push('parity')
+  }
+  if (wrap.hover === 'true') {
+    interaction.push('hover')
+  }
+
+  if (subtype === 'datacard') {
+    interOptions = [
+      {value: 'parity', label: '濂囧伓寮傝壊'},
+    ]
+    if (appType !== 'mob') {
+      interOptions.push(
+        {value: 'hover', label: '鎮诞鍙樿壊'},
+        {value: 'scale', label: '鎮诞鏀惧ぇ'}
+      )
+    }
+  } else if (subtype === 'propcard' && appType !== 'mob') {
+    interOptions = [
+      {value: 'scale', label: '鎮诞鏀惧ぇ'}
+    ]
+  } else if (subtype === 'tablecard') {
+    interOptions = [
+      {value: 'parity', label: '濂囧伓寮傝壊'},
+    ]
+    if (appType !== 'mob') {
+      interOptions.push(
+        {value: 'hover', label: '鎮诞鍙樿壊'}
+      )
+    }
+  }
+
+  if (interaction.length && interOptions.length) {
+    interaction = interaction.filter(m => interOptions.findIndex(cell => cell.value === m) > -1)
+  }
+
+  // let interItem = null
+
+  // if (interOptions.length === 1) {
+  //   interItem = {
+  //     type: 'radio',
+  //     field: interOptions[0].value,
+  //     label: interOptions[0].label,
+  //     initval: interaction.length === 1 ? 'true' : 'false',
+  //     required: false,
+  //     options: [
+  //       {value: 'true', label: '鍚敤'},
+  //       {value: 'false', label: '绂佺敤'}
+  //     ]
+  //   }
+  // } else {
+  //   interItem = {
+  //     type: 'checkbox',
+  //     field: 'interaction',
+  //     label: '浜や簰鏁堟灉',
+  //     initval: interaction,
+  //     required: false,
+  //     options: interOptions,
+  //     forbid: interOptions.length === 0
+  //   }
+  // }
+
   const cardWrapForm = [
     {
       type: 'text',
@@ -306,31 +374,27 @@
       ],
       forbid: subtype !== 'datacard' || appType === 'mob'
     },
+    // {
+    //   type: 'radio',
+    //   field: 'scale',
+    //   label: '鏀惧ぇ鏁堟灉',
+    //   initval: wrap.scale || 'false',
+    //   tooltip: '榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��',
+    //   required: false,
+    //   options: [
+    //     {value: 'false', label: '鏃�'},
+    //     {value: 'true', label: '鏈�'},
+    //   ],
+    //   forbid: subtype === 'tablecard' || appType === 'mob'
+    // },
     {
-      type: 'radio',
-      field: 'scale',
-      label: '鏀惧ぇ鏁堟灉',
-      initval: wrap.scale || 'false',
-      tooltip: '榧犳爣鎮诞浜庡崱鐗囦笂鏂规椂锛屽崱鐗囨斁澶�1.05鍊嶃��',
+      type: 'checkbox',
+      field: 'interaction',
+      label: '浜や簰鏁堟灉',
+      initval: interaction,
       required: false,
-      options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'true', label: '鏈�'},
-      ],
-      forbid: subtype === 'tablecard' || appType === 'mob'
-    },
-    {
-      type: 'radio',
-      field: 'parity',
-      label: '濂囧伓鑳屾櫙',
-      initval: wrap.parity || 'false',
-      tooltip: '鍋舵暟琛屼細娣诲姞鑳屾櫙鑹层��',
-      required: false,
-      options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'true', label: '鏈�'},
-      ],
-      forbid: subtype === 'propcard'
+      options: interOptions,
+      forbid: interOptions.length === 0
     },
     {
       type: 'radio',
@@ -449,7 +513,6 @@
       ],
       controlFields: [
         {field: 'jumpField', values: ['menu', 'link']},
-        {field: 'joint', values: ['menu', 'link']},
         {field: 'open', values: ['menu', 'link']},
         {field: 'menu', values: ['menu']},
         {field: 'link', values: ['link']},
@@ -483,18 +546,6 @@
       tooltip: '璺宠浆閾炬帴涓烘煡璇㈡暟鎹殑杩斿洖鍊笺��',
       required: true,
       options: columns,
-      forbid: subtype !== 'propcard' || appType !== 'mob'
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: wrap.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
       forbid: subtype !== 'propcard' || appType !== 'mob'
     },
     {
@@ -610,6 +661,19 @@
     },
     {
       type: 'radio',
+      field: 'searchBtn',
+      label: '鎼滅储鎸夐挳',
+      initval: wrap.searchBtn || 'hidden',
+      // tooltip: '鍚敤鎼滅储鏉′欢缂撳瓨鍚庯紝鍦ㄨ彍鍗曞埛鏂版椂鎼滅储鏉′欢涓嶅彉銆�',
+      required: false,
+      options: [
+        {value: 'hidden', label: '闅愯棌'},
+        {value: 'show', label: '鏄剧ず'},
+      ],
+      forbid: appType === 'mob' || isprint,
+    },
+    {
+      type: 'radio',
       field: 'shifting',
       label: '鎸夐挳鍋忕Щ',
       initval: wrap.shifting || 'false',
@@ -669,7 +733,7 @@
           width: '20%'
         },
         {
-          title: '鑿滃崟',
+          title: '缁勪欢',
           dataIndex: 'nodes',
           inputType: 'cascader',
           editable: true,
diff --git a/src/menu/components/card/double-data-card/index.scss b/src/menu/components/card/double-data-card/index.scss
index 40ea29c..722a29f 100644
--- a/src/menu/components/card/double-data-card/index.scss
+++ b/src/menu/components/card/double-data-card/index.scss
@@ -20,7 +20,7 @@
   }
 
   .card-item, .card-item-wrap {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-color: #ffffff;
     background-position: center center;
diff --git a/src/menu/components/card/double-data-card/options.jsx b/src/menu/components/card/double-data-card/options.jsx
index 16d9f40..7d632f0 100644
--- a/src/menu/components/card/double-data-card/options.jsx
+++ b/src/menu/components/card/double-data-card/options.jsx
@@ -133,21 +133,21 @@
       tooltip: '鏁版嵁鍗″彸涓婅浼氭樉绀烘敹璧峰紑鍏炽��',
       required: false,
       options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'true', label: '鏈�'},
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ],
       forbid: appType === 'mob'
     },
     {
       type: 'radio',
       field: 'parity',
-      label: '濂囧伓鑳屾櫙',
+      label: '濂囧伓寮傝壊',
       initval: wrap.parity || 'false',
-      tooltip: '鍋舵暟琛屼細娣诲姞鑳屾櫙鑹层��',
+      tooltip: '瀛愯〃鍋舵暟琛屼細娣诲姞鑳屾櫙鑹层��',
       required: false,
       options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'true', label: '鏈�'},
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ],
     },
     {
diff --git a/src/menu/components/card/doublecardcomponent/index.jsx b/src/menu/components/card/doublecardcomponent/index.jsx
index cc2e64a..0507417 100644
--- a/src/menu/components/card/doublecardcomponent/index.jsx
+++ b/src/menu/components/card/doublecardcomponent/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Popover, Col } from 'antd'
+import { Popover, Col, Modal, Button } from 'antd'
 import { UpOutlined, PlusOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, FontColorsOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -11,6 +11,8 @@
 import Utils from '@/utils/utils.js'
 import MKEmitter from '@/utils/events.js'
 import './index.scss'
+
+const { confirm } = Modal
 
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
@@ -28,6 +30,7 @@
     card: null,            // 鍗$墖淇℃伅锛屽寘鎷鍙嶉潰
     appType: sessionStorage.getItem('appType'),
     visible: false,
+    timestamp: '',
     side: ''
   }
 
@@ -38,7 +41,8 @@
     const { card } = this.props
 
     this.setState({
-      card: fromJS(card).toJS()
+      card: fromJS(card).toJS(),
+      timestamp: new Date().getTime() + ''
     })
   }
 
@@ -208,8 +212,118 @@
     this.props.updateElement(_card)
   }
 
+  updateFields = (elements, resolve, position, type) => {
+    const { card } = this.state
+
+    let items = elements
+
+    if (type === 'form') {
+      items = []
+
+      elements.forEach(item => {
+        let cell = {
+          uuid: Utils.getuuid(),
+          eleType: 'text',
+          height: 1,
+          innerHeight: 21,
+          prefix: item.label ? item.label + ': ' : '',
+          datatype: item.field ? 'dynamic' : 'static',
+          field: item.field || '',
+          width: item.span || 12,
+          value: '',
+          style: {marginBottom: '15px'}
+        }
+
+        if (item.type === 'number') {
+          cell.eleType = 'number'
+          cell.decimal = typeof(item.decimal) === 'number' ? item.decimal : ''
+        }
+
+        items.push(cell)
+      })
+    }
+
+    if (items.length === 0) {
+      resolve({status: false, message: '鍏冪礌涓嶅彲涓虹┖锛�'})
+      return
+    }
+
+    let _card = { ...card }
+    let _card2 = { ...card }
+    let pass = false
+
+    if (position === 'sub') {
+      if (_card.backElements.length === 0) {
+        _card.backElements = items
+        pass = true
+      } else {
+        _card.backElements = items
+        _card2.backElements = [...card.backElements, ...items]
+      }
+    } else {
+      if (_card.elements.length === 0) {
+        _card.elements = items
+        pass = true
+      } else {
+        _card.elements = items
+        _card2.elements = [...card.elements, ...items]
+      }
+    }
+
+    if (pass) {
+      this.setState({
+        card: _card,
+        timestamp: new Date().getTime() + ''
+      })
+
+      this.props.updateElement(_card)
+    } else {
+      const that = this
+      const _modal = confirm({
+        title: '鍗$墖涓凡瀛樺湪鍏冪礌锛岃閫夋嫨瑕佽繘琛岀殑鎿嶄綔銆�',
+        className: 'mk-confirm-modal',
+        content: <div className="footer">
+          <Button key="cancel" onClick={() => _modal.destroy()}>鍙栨秷</Button>
+          <Button key="replace" className="mk-border-purple" onClick={() => {
+            that.setState({
+              card: _card,
+              timestamp: new Date().getTime() + ''
+            })
+      
+            that.props.updateElement(_card)
+            _modal.destroy()
+          }}>鏇挎崲</Button>
+          <Button key="confirm" className="mk-border-green" onClick={() => {
+            that.setState({
+              card: _card2,
+              timestamp: new Date().getTime() + ''
+            })
+      
+            that.props.updateElement(_card2)
+            _modal.destroy()
+          }}>娣诲姞</Button>
+        </div>
+      })
+    }
+
+    resolve({status: true})
+  }
+
   paste = (element, resolve, type) => {
     const { card } = this.state
+
+    if (['simpleform', 'forms', 'formgroup', 'cardcell'].includes(element.copyType)) {
+      if (element.copyType === 'simpleform') {
+        this.updateFields(element.subcards[0].fields, resolve, type, 'form')
+      } else if (element.copyType === 'forms') {
+        this.updateFields(element.fields, resolve, type, 'form')
+      } else if (element.copyType === 'formgroup') {
+        this.updateFields(element.fields, resolve, type, 'form')
+      } else {
+        this.updateFields(element.elements, resolve, type)
+      }
+      return
+    }
 
     let _uuid = Utils.getuuid()
     
@@ -238,7 +352,7 @@
 
   render() {
     const { cards } = this.props
-    const { card } = this.state
+    const { card, timestamp } = this.state
 
     let _style = {...card.style}
     let _backStyle = {...card.backStyle}
@@ -288,14 +402,14 @@
                     <EditOutlined className="edit" title="缂栬緫"/>
                   </NormalForm>
                   <CopyComponent type="cardcell" card={{...card, backElements: []}}/>
-                  <PasteController options={['action', 'customCardElement']} updateConfig={(element, resolve) => this.paste(element, resolve, 'main')} />
+                  <PasteController options={['action', 'customCardElement', 'simpleform', 'forms', 'formgroup', 'cardcell']} updateConfig={(element, resolve) => this.paste(element, resolve, 'main')} />
                   <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.changeStyle()} />
                 </div>
               } trigger="hover">
                 <ToolOutlined />
               </Popover>
             </div>
-            <CardCellComponent cards={cards} cardCell={card} side="main" elements={card.elements} updateElement={(elements, btn) => this.updateCard(elements, btn)}/>
+            <CardCellComponent cards={cards} cardCell={card} side="main" timestamp={timestamp} elements={card.elements} updateElement={(elements, btn) => this.updateCard(elements, btn)}/>
           </div>
           <Col span={card.backSetting.width || 24}>
             <div className={'card-item ' + (card.backSetting.btnControl || '')} style={_backStyle} onDoubleClick={(e) => {e.stopPropagation(); this.doubleClickCard('sub')}} id={card.uuid}>
@@ -308,14 +422,14 @@
                       <EditOutlined className="edit" title="缂栬緫"/>
                     </NormalForm>
                     <CopyComponent type="cardcell" card={{...card, elements: card.backElements, backElements: []}}/>
-                    <PasteController options={['action', 'customCardElement']} updateConfig={(element, resolve) => this.paste(element, resolve, 'sub')} />
+                    <PasteController options={['action', 'customCardElement', 'simpleform', 'forms', 'formgroup', 'cardcell']} updateConfig={(element, resolve) => this.paste(element, resolve, 'sub')} />
                     <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.changeStyle('sub')} />
                   </div>
                 } trigger="hover">
                   <ToolOutlined />
                 </Popover>
               </div>
-              <CardCellComponent cards={cards} cardCell={card} side="sub" elements={card.backElements} updateElement={(elements, btn) => this.updateCard(elements, btn, 'sub')}/>
+              <CardCellComponent cards={cards} cardCell={card} side="sub" timestamp={timestamp} elements={card.backElements} updateElement={(elements, btn) => this.updateCard(elements, btn, 'sub')}/>
             </div>
           </Col>
         </div>
diff --git a/src/menu/components/card/doublecardcomponent/index.scss b/src/menu/components/card/doublecardcomponent/index.scss
index 63e0e13..cc9f94f 100644
--- a/src/menu/components/card/doublecardcomponent/index.scss
+++ b/src/menu/components/card/doublecardcomponent/index.scss
@@ -117,3 +117,16 @@
     display: inline-block;
   }
 }
+
+.mk-confirm-modal {
+  .ant-modal-confirm-btns {
+    display: none;
+  }
+  .footer {
+    margin-top: 24px;
+    text-align: right;
+    .ant-btn {
+      margin-left: 8px;
+    }
+  }
+}
diff --git a/src/menu/components/card/doublecardcomponent/options.jsx b/src/menu/components/card/doublecardcomponent/options.jsx
index 7100e7e..e47a287 100644
--- a/src/menu/components/card/doublecardcomponent/options.jsx
+++ b/src/menu/components/card/doublecardcomponent/options.jsx
@@ -109,7 +109,6 @@
         {field: 'menu', values: ['menu']},
         {field: 'linkurl', values: ['link']},
         {field: 'open', values: ['menu', 'link']},
-        {field: 'joint', values: ['menu', 'link']},
         {field: 'linkbtn', values: ['button']},
         {field: 'clickType', values: ['button', 'unfold']},
       ]
@@ -119,6 +118,7 @@
       field: 'menu',
       label: '鍏宠仈鑿滃崟',
       initval: setting.menu || (appType ? '' : []),
+      tooltip: `琛屼俊鎭�${appType ? '锛堝瓧娈甸泦涓墠40涓暱搴︿笉瓒呰繃256鐨勫瓧娈碉級' : ''}灏嗕紶閫掕嚦姝よ彍鍗曪紝鍙湪url鍙橀噺銆佽〃鍗曪紙鍏宠仈涓昏〃锛夈�侀潤鎬佸睘鎬у崱銆佹诞鍔ㄥ崱涓娇鐢ㄣ�俙,
       required: true,
       extendName: 'MenuNo',
       options: menulist,
@@ -128,6 +128,8 @@
       field: 'linkurl',
       label: '閾炬帴',
       initval: setting.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true,
       options: [],
       span: 24
@@ -143,17 +145,6 @@
         {value: 'self', label: appType !== 'mob' ? '褰撳墠绐楀彛' : '褰撳墠椤甸潰'},
       ],
       forbid: appType !== 'pc' && appType !== 'mob'
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: setting.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
     },
     {
       type: 'select',
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index ff9f81e..c0b2914 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -315,6 +315,13 @@
   updateWrap = (res) => {
     const { card } = this.state
 
+    if (res.interaction) {
+      if (res.interaction.includes('scale')) {
+        res.scale = 'true'
+      }
+      delete res.interaction
+    }
+
     let _card = {...card, wrap: res}
 
     if (res.datatype === 'static') {
diff --git a/src/menu/components/card/prop-card/index.scss b/src/menu/components/card/prop-card/index.scss
index 5e0c1e5..21c1ad6 100644
--- a/src/menu/components/card/prop-card/index.scss
+++ b/src/menu/components/card/prop-card/index.scss
@@ -19,7 +19,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-color: #ffffff;
     background-position: center center;
diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx
index dd96ddb..5672f99 100644
--- a/src/menu/components/card/table-card/index.jsx
+++ b/src/menu/components/card/table-card/index.jsx
@@ -271,6 +271,15 @@
   }
 
   updateWrap = (res) => {
+    if (res.interaction) {
+      if (res.interaction.includes('parity')) {
+        res.parity = 'true'
+      }
+      if (res.interaction.includes('hover')) {
+        res.hover = 'true'
+      }
+      delete res.interaction
+    }
     this.updateComponent({...this.state.card, wrap: res})
   }
 
diff --git a/src/menu/components/card/table-card/index.scss b/src/menu/components/card/table-card/index.scss
index aef713c..c8abd8b 100644
--- a/src/menu/components/card/table-card/index.scss
+++ b/src/menu/components/card/table-card/index.scss
@@ -63,6 +63,7 @@
   }
   .ant-pagination {
     text-align: right;
+    margin-top: 10px;
   }
   .mk-more {
     text-align: center;
diff --git a/src/menu/components/carousel/data-card/index.scss b/src/menu/components/carousel/data-card/index.scss
index 7d9fda3..7bbacd7 100644
--- a/src/menu/components/carousel/data-card/index.scss
+++ b/src/menu/components/carousel/data-card/index.scss
@@ -19,7 +19,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-position: center center;
     background-repeat: no-repeat;
diff --git a/src/menu/components/carousel/prop-card/index.scss b/src/menu/components/carousel/prop-card/index.scss
index 07e359f..6c50965 100644
--- a/src/menu/components/carousel/prop-card/index.scss
+++ b/src/menu/components/carousel/prop-card/index.scss
@@ -19,7 +19,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-position: center center;
     background-repeat: no-repeat;
diff --git a/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
index 2292bc0..3c67d5d 100644
--- a/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-G6/chartcompile/formconfig.jsx
@@ -129,7 +129,6 @@
         {field: 'menus', values: ['menus']},
         {field: 'menuType', values: ['menus']},
         {field: 'open', values: ['menu', 'menus']},
-        {field: 'joint', values: ['menu', 'menus']},
       ]
     },
     {
@@ -160,17 +159,6 @@
         {value: 'self', label: '褰撳墠绐楀彛'},
       ],
       forbid: appType !== 'pc'
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: card.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
     },
     {
       type: 'table',
diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
index 7946f54..a808760 100644
--- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -128,7 +128,6 @@
       controlFields: [
         {field: 'menu', values: ['menu']},
         {field: 'open', values: ['menu', 'menus']},
-        {field: 'joint', values: ['menu', 'menus']},
         {field: 'menuType', values: ['menus']},
         {field: 'menus', values: ['menus']},
       ]
@@ -165,19 +164,6 @@
         {value: 'self', label: '褰撳墠绐楀彛'},
       ],
       forbid: appType !== 'pc' || card.chartType !== 'bar',
-      hidden: card.click !== 'menu' && card.click !== 'menus'
-    },
-    {
-      type: 'radio',
-      field: 'joint',
-      label: '鍙傛暟鎷兼帴',
-      initval: card.joint || 'true',
-      required: false,
-      options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
-      ],
-      forbid: appType === 'mob' || card.chartType !== 'bar',
       hidden: card.click !== 'menu' && card.click !== 'menus'
     },
     {
diff --git a/src/menu/components/chart/chart-custom/index.jsx b/src/menu/components/chart/chart-custom/index.jsx
index 5dc3f45..d5ba312 100644
--- a/src/menu/components/chart/chart-custom/index.jsx
+++ b/src/menu/components/chart/chart-custom/index.jsx
@@ -4,7 +4,6 @@
 import { Popover, notification } from 'antd'
 import { ToolOutlined, DeleteOutlined, FontColorsOutlined, PlusCircleOutlined } from '@ant-design/icons'
 import { Chart } from '@antv/g2'
-import DataSet from '@antv/data-set'
 import * as echarts from 'echarts'
 
 import MKEmitter from '@/utils/events.js'
@@ -137,8 +136,8 @@
     if (card.plot.chartType === 'antv') {
       try {
         // eslint-disable-next-line
-        let func = new Function('Chart', 'DataSet', 'wrap', 'data', 'config', card.plot.script)
-        func(Chart, DataSet, this.wrap, [], card)
+        let func = new Function('Chart', 'chartId', 'data', 'config', card.plot.script)
+        func(Chart, card.uuid + 'canvas', [], card)
       } catch (e) {
         console.warn(e)
   
@@ -151,8 +150,8 @@
     } else if (card.plot.chartType === 'echarts') {
       try {
         // eslint-disable-next-line
-        let func = new Function('echarts', 'DataSet', 'wrap', 'data', 'config', card.plot.script)
-        func(echarts, DataSet, this.wrap, [], card)
+        let func = new Function('echarts', 'chartId', 'data', 'config', card.plot.script)
+        func(echarts, card.uuid + 'canvas', [], card)
       } catch (e) {
         console.warn(e)
   
@@ -262,7 +261,7 @@
         </Popover>
         <NormalHeader config={card} updateComponent={this.updateComponent}/>
         <div className="canvas-wrap" style={{height: card.plot.height}}>
-          <div className="canvas" id={card.uuid + 'canvas'} style={{height: getHeight(card.plot.height)}} ref={ref => this.wrap = ref}></div>
+          <div className="canvas" id={card.uuid + 'canvas'} style={{height: getHeight(card.plot.height)}}></div>
         </div>
         <div className="component-name">
           <div className="center">
diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx
index 09c15d7..33ebafb 100644
--- a/src/menu/components/form/formaction/actionform/index.jsx
+++ b/src/menu/components/form/formaction/actionform/index.jsx
@@ -57,7 +57,7 @@
     } else if (this.record.type === 'close' || this.record.type === 'reset') {
       shows = ['typeName', 'label']
     } else {
-      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton', 'formCache'] // 閫夐」鍒楄〃
+      shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload', 'preButton', 'refreshTab'] // 閫夐」鍒楄〃
 
       if (this.record.execSuccess === 'never') {
         shows.push('resetForms')
@@ -176,6 +176,15 @@
     this.state.formlist.forEach((item, index) => {
       if (item.hidden || item.forbid) return
 
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
+
       if (item.type === 'text') {
         let _rules = []
         if (item.key === 'innerFunc') {
@@ -222,12 +231,7 @@
         }
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -244,7 +248,7 @@
       } else if (item.type === 'tip') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {item.initVal}
             </Form.Item>
           </Col>
@@ -252,12 +256,7 @@
       } else if (item.type === 'number') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -273,12 +272,7 @@
       } else if (item.type === 'select') { // 涓嬫媺鎼滅储
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item help={item.help || null} label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item help={item.help || null} label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -309,12 +303,7 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -340,7 +329,7 @@
       } else if (item.type === 'textarea') {
         fields.push(
           <Col span={24} key={index}>
-            <Form.Item label={item.label} className="textarea">
+            <Form.Item label={label} className="textarea">
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -356,12 +345,7 @@
       } else if (item.type === 'cascader') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || [],
                 rules: [
diff --git a/src/menu/components/form/formaction/formconfig.jsx b/src/menu/components/form/formaction/formconfig.jsx
index 1a4e306..e3bc348 100644
--- a/src/menu/components/form/formaction/formconfig.jsx
+++ b/src/menu/components/form/formaction/formconfig.jsx
@@ -123,6 +123,14 @@
     })
   }
 
+  let closetab = []
+  if (!appType && viewType !== 'popview') {
+    closetab = [{
+      value: 'closetab',
+      text: '鍏抽棴鏍囩'
+    }]
+  }
+
   let resets = []
   fields.forEach(item => {
     if (item.type !== 'text' && item.type !== 'number') return
@@ -246,7 +254,7 @@
       initVal: card.innerFunc || '',
       tooltip: functip,
       fields: usefulFields,
-      tooltipClass: 'middle',
+      toolWidth: 350,
       required: true,
       readonly: false
     },
@@ -431,7 +439,20 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
-      }, ...refresh]
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
+      }, ...closetab, ...refresh]
+    },
+    {
+      type: 'cascader',
+      key: 'refreshTab',
+      label: '鍒锋柊鑿滃崟',
+      initVal: card.refreshTab || [],
+      tooltip: '鎵ц鎴愬姛鍚庯紙鎴栧姛鑳芥寜閽腑鏍囩鍏抽棴绫诲瀷锛夛紝闇�瑕佸悓姝ュ埛鏂扮殑鑿滃崟',
+      required: false,
+      forbid: appType === 'pc' || appType === 'mob' || viewType === 'popview',
+      options: menulist
     },
     {
       type: (appType === 'pc' || appType === 'mob') ? 'select' : 'cascader',
@@ -539,21 +560,6 @@
         value: 'true',
         text: '鍒锋柊'
       }]
-    },
-    // {
-    //   type: 'radio',
-    //   key: 'formCache',
-    //   label: '琛ㄥ崟缂撳瓨',
-    //   initVal: card.formCache || 'false',
-    //   tooltip: '涓昏鐢ㄤ簬鏁版嵁淇敼鍚庯紝鏇存柊鐩稿叧琛ㄥ崟鐨勯�夐」锛屾竻绌虹紦瀛樺悗琛ㄥ崟鍐嶆鎵撳紑鏃舵暟鎹細閲嶆柊鍔犺浇銆�',
-    //   required: false,
-    //   options: [{
-    //     value: 'false',
-    //     text: '涓嶆竻绌�'
-    //   }, {
-    //     value: 'clear',
-    //     text: '娓呯┖'
-    //   }]
-    // },
+    }
   ]
 }
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 3a0bf93..2d1855a 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -375,7 +375,7 @@
         })
       }
 
-      if (item.type === 'switch' || item.type === 'check') {
+      if (['switch', 'check', 'popSelect'].includes(item.type)) {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -481,6 +481,10 @@
   pasteForm = (forms, res) => {
     let _config = fromJS(this.state.card).toJS()
 
+    forms.forEach(item => {
+      delete item.focus
+    })
+
     _config.subcards[0].fields = forms
 
     if (res.subButton) {
@@ -511,8 +515,6 @@
         }
       })
     } else {
-      _config.subcards[0].fields = forms
-
       this.updateComponent(_config)
     }
   }
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index dd919dc..8704f5e 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -477,7 +477,7 @@
         })
       }
 
-      if (item.type === 'switch' || item.type === 'check') {
+      if (['switch', 'check', 'popSelect'].includes(item.type)) {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -592,6 +592,7 @@
 
     res.fields.forEach(item => {
       item.uuid = Utils.getuuid()
+      delete item.focus
     })
 
     if (!res.prevButton) {
diff --git a/src/menu/components/form/step-form/options.jsx b/src/menu/components/form/step-form/options.jsx
index 1ec6a9e..647d7a0 100644
--- a/src/menu/components/form/step-form/options.jsx
+++ b/src/menu/components/form/step-form/options.jsx
@@ -128,9 +128,23 @@
         {value: 'show', label: '鏄剧ず'},
         {value: 'hidden', label: '闅愯棌'},
       ],
-      // controlFields: [
-      //   {field: 'labelSize', values: ['show']},
-      // ]
+      controlFields: [
+        // {field: 'labelSize', values: ['show']},
+        {field: 'labelJump', values: ['show']},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'labelJump',
+      label: '鍚嶇О鍒囨崲',
+      initval: wrap.labelJump || 'false',
+      tooltip: '寮�鍚椂锛屽彲閫氳繃鐐瑰嚮鍒嗙粍鍚嶇О鍚戝墠璺宠浆銆�',
+      required: false,
+      forbid: config.subtype === 'tabform',
+      options: [
+        {value: 'false', label: '鍏抽棴'},
+        {value: 'true', label: '寮�鍚�'},
+      ]
     },
     // {
     //   type: 'number',
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index 66e8181..8ee36a7 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -482,7 +482,7 @@
         })
       }
 
-      if (item.type === 'switch' || item.type === 'check') {
+      if (['switch', 'check', 'popSelect'].includes(item.type)) {
         _linksupFields.push({
           field: item.field,
           label: item.label
@@ -597,6 +597,7 @@
 
     res.fields.forEach(item => {
       item.uuid = Utils.getuuid()
+      delete item.focus
     })
 
     delete res.prevButton
diff --git a/src/menu/components/group/normal-group/index.scss b/src/menu/components/group/normal-group/index.scss
index f616fad..8d1307c 100644
--- a/src/menu/components/group/normal-group/index.scss
+++ b/src/menu/components/group/normal-group/index.scss
@@ -1,7 +1,7 @@
 .menu-group-edit-box {
   position: relative;
   box-sizing: border-box;
-  background: #ffffff;
+  // background: #ffffff;
   background-position: center center;
   background-repeat: no-repeat;
   background-size: cover;
diff --git a/src/menu/components/group/normal-group/options.jsx b/src/menu/components/group/normal-group/options.jsx
index 8b4c290..521a003 100644
--- a/src/menu/components/group/normal-group/options.jsx
+++ b/src/menu/components/group/normal-group/options.jsx
@@ -122,6 +122,34 @@
       ]
     },
     {
+      type: 'radio',
+      field: 'mergeAble',
+      label: '灞曞紑/鏀惰捣',
+      initval: setting.mergeAble || 'false',
+      tooltip: '鍚敤鏃讹紝缁勪欢鍙充笂瑙掑皢鍑虹幇灞曞紑/鏀惰捣鐨勫浘鏍囷紝鍙皢褰撳墠缁勪欢灞曞紑鎴栨敹璧枫��',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      controlFields: [
+        {field: 'ctrlNumber', values: ['true']},
+      ],
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'number',
+      field: 'ctrlNumber',
+      label: '鎺у埗鏁�',
+      initval: setting.ctrlNumber || 1,
+      tooltip: '褰撶粍浠舵敹璧锋椂锛屽叾鍚庨渶瑕佸睍寮�鐨勭粍浠舵暟銆�',
+      min: 1,
+      max: 5,
+      precision: 0,
+      required: true,
+      forbid: appType === 'mob'
+    },
+    {
       type: 'multiselect',
       field: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/module/account/index.jsx b/src/menu/components/module/account/index.jsx
index db814a9..3ddeffa 100644
--- a/src/menu/components/module/account/index.jsx
+++ b/src/menu/components/module/account/index.jsx
@@ -80,7 +80,7 @@
   changeStyle = () => {
     const { card } = this.state
 
-    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
+    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear', 'position'], card.style, this.getStyle)
   }
 
   getStyle = (style) => {
diff --git a/src/menu/components/module/account/index.scss b/src/menu/components/module/account/index.scss
index e69767f..acdc8bf 100644
--- a/src/menu/components/module/account/index.scss
+++ b/src/menu/components/module/account/index.scss
@@ -1,5 +1,5 @@
 .menu-account-box {
-  position: relative;
+  position: relative!important;
   box-sizing: border-box;
   background: #ffffff;
   background-position: center center;
diff --git a/src/menu/components/module/invoice/index.jsx b/src/menu/components/module/invoice/index.jsx
new file mode 100644
index 0000000..8a17449
--- /dev/null
+++ b/src/menu/components/module/invoice/index.jsx
@@ -0,0 +1,495 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Popover, Button, Modal } from 'antd'
+import { EditOutlined, ToolOutlined, DeleteOutlined, LeftOutlined, FontColorsOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons'
+import moment from 'moment'
+
+import Utils from '@/utils/utils.js'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import { getTables, checkComponent } from '@/utils/utils-custom.js'
+import MKEmitter from '@/utils/events.js'
+import VerifyCard from './verifycard'
+import getWrapForm from './options'
+
+import './index.scss'
+
+const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+
+class Invoice extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    deletecomponent: PropTypes.func,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    card: null,
+    date: moment().format('YYYY骞碝M鏈�'),
+    btn: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: false,    // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        width: card.width || 24,
+        name: '鍙戠エ',
+        subtype: card.subtype,
+        fixedCol: true,
+        wrap: { name: '鍙戠エ', width: card.width || 24, datatype: 'static' },
+        style: { paddingLeft: '20px', paddingRight: '20px', paddingTop: '10px', paddingBottom: '10px' },
+        setting: { interType: 'system', primaryKey: 'ID' },
+        columns: [],
+        scripts: [],
+        buyer: {
+          pageable: true,
+          format: 'array',
+          fixedCol: true,
+          subtype: 'invTable',
+          setting: { interType: 'system' },
+          columns: [],
+          scripts: [],
+          search: [
+            {field: 'from_to_name', label: '浼佷笟鍚嶇О', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
+            {field: 'from_to_tax_no', label: '浼佷笟绋庡彿', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
+          ],
+        },
+        detail: {
+          pageable: true,
+          format: 'array',
+          fixedCol: true,
+          subtype: 'invTable',
+          setting: { interType: 'system' },
+          columns: [],
+          scripts: [],
+          search: [
+            {field: 'productname', label: '鍟嗗搧鍚嶇О', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
+            {field: 'productcode', label: '鍟嗗搧缂栫爜', initval: '', type: 'text', match: 'like', uuid: Utils.getuuid()},
+          ],
+        },
+        billSaveBtn: {type: 'billsave', parId: card.uuid, intertype: 'system', label: '淇濆瓨鍗曟嵁'},
+        billOutBtn: {type: 'billout', parId: card.uuid, intertype: 'custom', label: '鎻愪氦寮�绁�', procMode: 'system'},
+      }
+
+      let buys = [
+        ['浼佷笟鍚嶇О', 'from_to_name'],
+        ['浼佷笟绋庡彿', 'from_to_tax_no'],
+        ['鍦板潃', 'from_to_addr', 'Nvarchar(100)'],
+        ['鐢佃瘽', 'from_to_tel'],
+        ['寮�鎴疯', 'from_to_bank_name'],
+        ['閾惰璐﹀彿', 'from_to_account_no'],
+        ['鎵嬫満鍙�', 'from_to_mob'],
+        ['閭', 'from_to_email'],
+        ['浼佷笟缂栫爜', 'from_to_code']
+      ]
+
+      buys.forEach((cell, index) => {
+        _card.buyer.columns.push({$index: index + 1, datatype: 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()})
+      })
+
+      let details = [
+        ['id', 'id'],
+        ['鍟嗗搧缂栫爜', 'productcode'],
+        ['鍟嗗搧鍚嶇О', 'productname'],
+        ['瑙勬牸鍨嬪彿', 'spec'],
+        ['鎻忚堪', 'Description'],
+        ['璁¢噺鍗曚綅', 'unit'],
+        ['鍗曚环', 'unitprice', 'Decimal(18,10)'],
+        ['绋庡姟鍒嗙被缂栫爜', 'tax_classify_code'],
+        ['绋庡姟鍒嗙被鍚嶇О', 'tax_classify_name'],
+        ['涓�鑸撼绋庝汉绋庣巼', 'general_tax_rate', 'Decimal(18,2)'],
+        ['灏忚妯$撼绋庝汉寰佹敹鐜�', 'small_tax_rate', 'Decimal(18,2)'],
+        ['鏄惁浜彈浼樻儬鏀跨瓥', 'free_tax_mark'],
+        ['浼樻儬鏀跨瓥绫诲瀷', 'vat_special_management'],
+        ['寰佺◣椤圭洰', 'tax_item'],
+        ['璁$◣鏂规硶', 'tax_method'],
+      ]
+
+      details.forEach((cell, index) => {
+        _card.detail.columns.push({$index: index + 1, datatype: cell[2] || 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()})
+      })
+
+      let cols = [
+        ['ID', 'ID'],
+        ['寮�绁ㄧ敵璇峰崟鍙�', 'io'],
+        ['鍙戠エ绉嶇被', 'invoice_type'],
+        ['寮�绁ㄧ被鍨�', 'business_type', 'Nvarchar(20)'],
+        ['璐拱鏂瑰悕绉�', 'from_to_name'],
+        ['璐拱鏂圭◣鍙�', 'from_to_tax_no'],
+        ['璐拱鏂瑰湴鍧�', 'from_to_addr', 'Nvarchar(100)'],
+        ['璐拱鏂圭數璇�', 'from_to_tel'],
+        ['璐拱鏂瑰紑鎴疯', 'from_to_bank_name'],
+        ['璐拱鏂归摱琛岃处鍙�', 'from_to_account_no'],
+        ['璐拱鏂规墜鏈哄彿', 'from_to_mob'],
+        ['璐拱鏂归偖绠�', 'from_to_email'],
+        ['璐拱鏂圭紪鐮�', 'from_to_code'],
+        ['閿�鍞柟鍚嶇О', 'orgname'],
+        ['閿�鍞柟绋庡彿', 'tax_no'],
+        ['閿�鍞柟鍦板潃', 'addr', 'Nvarchar(100)'],
+        ['閿�鍞柟鐢佃瘽', 'tel'],
+        ['閿�鍞柟寮�鎴疯', 'bank_name'],
+        ['閿�鍞柟閾惰璐﹀彿', 'account_no'],
+        ['澶囨敞', 'remark', 'Nvarchar(512)'],
+        ['鏀舵浜�', 'payee'],
+        ['澶嶆牳浜�', 'reviewer'],
+        ['寮�绁ㄤ汉', 'drawer'],
+        ['jskey', 'jskey'],
+        ['琛屽彿', 'invoice_lp'],
+        ['鍟嗗搧缂栫爜', 'productcode'],
+        ['鍟嗗搧鍚嶇О', 'productname'],
+        ['瑙勬牸鍨嬪彿', 'spec'],
+        ['璁¢噺鍗曚綅', 'unit'],
+        ['鏁伴噺', 'bill_count', 'Decimal(18,10)'],
+        ['鍗曚环', 'unitprice', 'Decimal(18,10)'],
+        ['閲戦', 'amount_line', 'Decimal(18,2)'],
+        ['绋庡姟鍒嗙被缂栫爜', 'tax_classify_code'],
+        ['绋庡姟鍒嗙被鍚嶇О', 'tax_classify_name'],
+        ['绋庣巼', 'tax_rate', 'Decimal(18,2)'],
+        ['绋庨', 'tax_amount', 'Decimal(18,2)'],
+        ['鏄惁浜彈浼樻儬鏀跨瓥', 'free_tax_mark'],
+        ['浼樻儬鏀跨瓥绫诲瀷', 'vat_special_management'],
+        ['寰佺◣椤圭洰', 'tax_item'],
+        ['璁$◣鏂规硶', 'tax_method'],
+        ['鍙戠エ鍙风爜', 'invoice_no'],
+        ['鍙戠エ浠g爜', 'invoice_code'],
+        ['寮�绁ㄦ棩鏈�', 'invoice_date'],
+        ['鍙(true)', 'read_only'],
+      ]
+
+      cols.forEach((cell, index) => {
+        _card.columns.push({$index: index + 1, datatype: cell[2] || 'Nvarchar(50)', field: cell[1], label: cell[0], uuid: Utils.getuuid()})
+      })
+
+      this.updateComponent(_card)
+    } else {
+      let _card = fromJS(card).toJS()
+
+      this.setState({
+        card: _card
+      })
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (card) => {
+    card.width = card.wrap.width
+    card.name = card.wrap.name
+    
+    if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
+      this.setState({
+        card: card
+      })
+  
+      this.props.updateConfig(card)
+      return
+    }
+
+    card.$c_ds = card.wrap.datatype === 'dynamic'
+    card.errors = checkComponent(card)
+
+    if (card.errors.length === 0) {
+      if (card.buyer.setting.interType === 'system' && card.buyer.setting.execute !== 'false' && !card.buyer.setting.dataresource) {
+        card.errors.push({ level: 0, detail: '-璐拱鏂� 鏈缃暟鎹簮锛�'})
+      } else if (card.buyer.setting.interType === 'system' && card.buyer.setting.execute === 'false' && card.buyer.scripts.filter(script => script.status !== 'false').length === 0) {
+        card.errors.push({ level: 0, detail: '-璐拱鏂� 鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+      }
+    }
+    if (card.errors.length === 0) {
+      if (card.detail.setting.interType === 'system' && card.detail.setting.execute !== 'false' && !card.detail.setting.dataresource) {
+        card.errors.push({ level: 0, detail: '-鏄庣粏 鏈缃暟鎹簮锛�'})
+      } else if (card.detail.setting.interType === 'system' && card.detail.setting.execute === 'false' && card.detail.scripts.filter(script => script.status !== 'false').length === 0) {
+        card.errors.push({ level: 0, detail: '-鏄庣粏 鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+      }
+    }
+
+    if (!card.billSaveBtn.scripts || card.billSaveBtn.scripts.length === 0) {
+      card.errors.push({ level: 0, detail: '鏈坊鍔犲崟鎹繚瀛樿剼鏈紒'})
+    // } else if (!card.billOutBtn.scripts || card.billOutBtn.scripts.length === 0) {
+    //   card.errors.push({ level: 0, detail: '鏈坊鍔犳彁浜ゅ紑绁ㄥ墠缃剼鏈紒'})
+    // } else if (card.billSaveBtn.cbScripts.length === 0) {
+    //   card.errors.push({ level: 0, detail: '鏈坊鍔犳彁浜ゅ紑绁ㄥ洖璋冭剼鏈紒'})
+    }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+      card.$tables = [...card.$tables, ...getTables(card.buyer)]
+      card.$tables = [...card.$tables, ...getTables(card.detail)]
+    }
+
+    this.setState({
+      card: card
+    })
+
+    this.props.updateConfig(card)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', ['background', 'border', 'padding', 'margin', 'shadow', 'clear'], card.style, this.getStyle)
+  }
+
+  getStyle = (style) => {
+    let _card = {...this.state.card, style}
+    
+    this.updateComponent(_card)
+  }
+
+  getWrapForms = () => {
+    const { card } = this.state
+
+    return getWrapForm(card.wrap)
+  }
+
+  updateWrap = (res) => {
+    this.updateComponent({...this.state.card, wrap: res})
+  }
+
+  verifySubmit = () => {
+    this.verifyRef.handleConfirm().then(res => {
+      if (res.type === 'billout') {
+        this.updateComponent({...this.state.card, billOutBtn: res})
+      } else {
+        this.updateComponent({...this.state.card, billSaveBtn: res})
+      }
+
+      this.setState({ btn: null })
+    })
+  }
+
+  render() {
+    const { card, date, btn } = this.state
+
+    let style = {...card.style}
+    if (card.wrap.invColor) {
+      style['--inv-color'] = card.wrap.invColor
+    }
+
+    return (
+      <div className="menu-invoice-box" style={style} id={card.uuid}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <NormalForm title="鍩烘湰璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+              <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
+            </NormalForm>
+            <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
+            <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
+            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
+          </div>
+        } trigger="hover">
+          <ToolOutlined />
+        </Popover>
+        <div className="inv-action">
+          {card.wrap.backBtn === 'show' ? <Button className="mk-back"><LeftOutlined />杩斿洖</Button> : null}
+          <Button className="mk-addinv">鏂板鍙戠エ</Button>
+          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+            <div className="mk-popover-control">
+              <EditOutlined style={{color: '#1890ff'}} onClick={() => this.setState({btn: card.billSaveBtn})} title="缂栬緫"/>
+            </div>
+          } trigger="hover">
+            <Button className="mk-bill">淇濆瓨鍗曟嵁</Button>
+          </Popover>
+          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+            <div className="mk-popover-control">
+              <EditOutlined style={{color: '#1890ff'}} onClick={() => this.setState({btn: card.billOutBtn})} title="缂栬緫"/>
+            </div>
+          } trigger="hover">
+            <Button className="mk-submit">鎻愪氦寮�绁�</Button>
+          </Popover>
+        </div>
+        <div className="inv-header">
+          <div className="mk-select">璇烽�夋嫨鍙戠エ绉嶇被</div>
+          <div className="date">寮�绁ㄦ棩鏈燂細{date}</div>
+        </div>
+        <div className="inv-body">
+          <div className="inv-main-content">
+            <div className="inv-buyer">
+              <div className="inv-label">璐拱鏂�</div>
+              <div className="inv-content">
+                <div className="mk-input">
+                  <label>鍚嶇О锛�</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟鍚嶇О</span>
+                  <span className="extra">
+                    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+                      <div className="mk-popover-control">
+                        <SettingComponent config={card.buyer} updateConfig={(res) => this.updateComponent({...card, buyer: res})} />
+                      </div>
+                    } trigger="hover">
+                      <EllipsisOutlined />
+                    </Popover>
+                  </span>
+                </div>
+                <div className="mk-input">
+                  <label>绾崇◣浜鸿瘑鍒彿锛�</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟绾崇◣浜鸿瘑鍒彿</span>
+                </div>
+                <div className="mk-input">
+                  <label>鍦板潃銆佺數璇濓細</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟鍦板潃</span>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟鐢佃瘽</span>
+                </div>
+                <div className="mk-input">
+                  <label>寮�鎴疯鍙婅处鍙凤細</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟寮�鎴疯</span>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟璐﹀彿</span>
+                </div>
+              </div>
+            </div>
+            <div className="inv-notice">
+              <div className="inv-label">閫氱煡鍒�</div>
+              <div className="inv-content">
+                <div className="mk-input">
+                  <label>鎵嬫満鍙凤細</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟鎵嬫満鍙�</span>
+                </div>
+                <div className="mk-input">
+                  <label>閭锛�</label>
+                  <span className="content">璇疯緭鍏ヨ喘涔版柟閭</span>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div className="inv-details">
+            <div className="detail-wrap">
+              <div className="mk-th">
+                <div className="mk-td">璐х墿鎴栧簲绋庡姵鍔°�佹湇鍔″悕绉�</div>
+                <div className="mk-td">瑙勬牸鍨嬪彿</div>
+                <div className="mk-td">鍗曚綅</div>
+                <div className="mk-td">鏁伴噺</div>
+                <div className="mk-td">鍗曚环锛堝惈绋庯級</div>
+                <div className="mk-td">閲戦锛堝惈绋庯級</div>
+                <div className="mk-td">绋庣巼</div>
+                <div className="mk-td">绋庨</div>
+              </div>
+              <div className="mk-tr">
+                <div className="mk-td mk-left">
+                  <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+                    <div className="mk-popover-control">
+                      <SettingComponent config={card.detail} updateConfig={(res) => this.updateComponent({...card, detail: res})} />
+                    </div>
+                  } trigger="hover">
+                    <EllipsisOutlined />
+                  </Popover>
+                </div>
+                <div className="mk-td mk-left"></div>
+                <div className="mk-td mk-left"></div>
+                <div className="mk-td mk-right"></div>
+                <div className="mk-td mk-right"></div>
+                <div className="mk-td mk-right"></div>
+                <div className="mk-td mk-right"></div>
+                <div className="mk-td mk-right"></div>
+              </div>
+              <div className="mk-total">
+                <div className="mk-td">鍚堣</div>
+                <div className="mk-td"></div>
+                <div className="mk-td"></div>
+                <div className="mk-td"></div>
+                <div className="mk-td"></div>
+                <div className="mk-td">锟�12</div>
+                <div className="mk-td"></div>
+                <div className="mk-td">锟�1</div>
+              </div>
+              <div className="mk-upcase">
+                <div className="mk-td">浠风◣鍚堣锛堝ぇ鍐欙級</div>
+                <div className="mk-td"></div>
+                <div className="mk-td">锛堝皬鍐欙級锟�12</div>
+              </div>
+            </div>
+          </div>
+          <div className="inv-main-content">
+            <div className="inv-buyer">
+              <div className="inv-label">閿�鍞柟</div>
+              <div className="inv-content">
+                <div className="mk-input">
+                  <label>鍚嶇О锛�</label>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟鍚嶇О</span>
+                </div>
+                <div className="mk-input">
+                  <label>绾崇◣浜鸿瘑鍒彿锛�</label>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟绾崇◣浜鸿瘑鍒彿</span>
+                </div>
+                <div className="mk-input">
+                  <label>鍦板潃銆佺數璇濓細</label>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟鍦板潃</span>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟鐢佃瘽</span>
+                </div>
+                <div className="mk-input">
+                  <label>寮�鎴疯鍙婅处鍙凤細</label>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟寮�鎴疯</span>
+                  <span className="content">璇疯緭鍏ラ攢鍞柟璐﹀彿</span>
+                </div>
+              </div>
+            </div>
+            <div className="inv-notice">
+              <div className="inv-label">澶囨敞</div>
+              <div className="inv-content" style={{paddingTop: '30px'}}>
+                <div className="mk-input">
+                  <span className="content" style={{height: '80px'}}>璇疯緭鍏ュ娉�</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div className="inv-tail">
+          <div className="mk-input">
+            <label>鏀舵浜猴細</label>
+            <span className="content">鏀舵浜�</span>
+          </div>
+          <div className="mk-input">
+            <label>澶嶆牳浜猴細</label>
+            <span className="content">澶嶆牳浜�</span>
+          </div>
+          <div className="mk-input">
+            <label>寮�绁ㄤ汉锛�</label>
+            <span className="content">寮�绁ㄤ汉</span>
+          </div>
+        </div>
+        <Modal
+          wrapClassName="mk-pop-modal"
+          visible={btn !== null}
+          width={'90vw'}
+          maskClosable={false}
+          okText="鎻愪氦"
+          onOk={this.verifySubmit}
+          onCancel={() => {
+            if (this.verifyRef.handleCancel) {
+              this.verifyRef.handleCancel().then(() => {
+                this.setState({ btn: null })
+              })
+            } else {
+              this.setState({ btn: null })
+            }
+          }}
+          destroyOnClose
+        >
+          <VerifyCard card={btn} wrappedComponentRef={(inst) => this.verifyRef = inst}/>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default Invoice
\ No newline at end of file
diff --git a/src/menu/components/module/invoice/index.scss b/src/menu/components/module/invoice/index.scss
new file mode 100644
index 0000000..49cfa86
--- /dev/null
+++ b/src/menu/components/module/invoice/index.scss
@@ -0,0 +1,272 @@
+.menu-invoice-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  color: #000000;
+  --inv-color: #13509c;
+
+  .anticon-tool {
+    position: absolute;
+    z-index: 2;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+
+  .inv-action {
+    text-align: right;
+    margin-right: 30px;
+    .ant-btn {
+      margin-left: 15px;
+      margin-bottom: 5px;
+      height: 30px;
+    }
+    .mk-back {
+      border: none;
+      float: left;
+      margin-left: 0px;
+      padding: 0px;
+      box-shadow: none;
+    }
+    .mk-back::after {
+      display: none;
+    }
+    .mk-addinv, .mk-addinv:active, .mk-addinv:focus {
+      color: #52c41a;
+      border-color: #52c41a;
+    }
+    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
+      color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .mk-submit, .mk-submit:hover, .mk-submit:active, .mk-submit:focus {
+      color: #fff;
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+  }
+  .inv-header {
+    text-align: center;
+    position: relative;
+    height: 70px;
+    margin-right: 30px;
+    .mk-select {
+      position: relative;
+      display: inline-block;
+      width: 390px;
+      font-size: 25px;
+      text-align: center;
+      font-family: kaiti;
+      color: var(--inv-color, #13509c);
+    }
+    .mk-select::before, .mk-select::after {
+      content: '';
+      display: block;
+      width: 100%;
+      position: absolute;
+      border-top: var(--inv-color, #13509c) 1px solid;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+      height: 1px;
+    }
+    .mk-select::before {
+      bottom: -10px;
+    }
+    .mk-select::after {
+      bottom: -15px;
+    }
+    .date {
+      position: absolute;
+      right: 100px;
+      top: 5px;
+      color: var(--inv-color, #13509c);
+    }
+  }
+
+  .mk-input {
+    position: relative;
+    height: 28px;
+    font-size: 13px;
+    background: transparent;
+    display: flex;
+    padding: 0 5px 0 15px;
+    margin-bottom: 5px;
+    label {
+      display: inline-block;
+      height: 28px;
+      line-height: 28px;
+      text-align: right;
+      color: var(--inv-color, #13509c);
+    }
+    span {
+      display: inline-block;
+      height: 28px;
+      line-height: 28px;
+    }
+    .extra {
+      position: absolute;
+      right: 0px;
+      .anticon-ellipsis {
+        padding: 0 15px;
+      }
+    }
+    .content {
+      flex: 1;
+      border-bottom: 1px solid #d9d9d9;
+      color: #b8b8b8;
+      transition: all 0.3s;
+      padding: 0px 10px;
+    }
+  }
+  .mk-input:hover .content {
+    border-color: var(--inv-color, #13509c);
+  }
+
+  .inv-body {
+    border: var(--inv-color, #13509c) 1px solid;
+    font-size: 13px;
+    margin-right: 30px;
+
+    .inv-main-content {
+      display: flex;
+
+      .inv-buyer, .inv-notice {
+        width: 50%;
+        display: flex;
+        .inv-label {
+          color: var(--inv-color, #13509c);
+          width: 6.25%;
+          display: flex;
+          flex-direction: column;
+          writing-mode: vertical-rl;
+          justify-content: center;
+          align-items: center;
+          letter-spacing: 5px;
+          border-right: var(--inv-color, #13509c) 1px solid;
+        }
+        .inv-content {
+          flex: 1;
+          padding: 8px 0;
+        }
+      }
+      .inv-buyer {
+        border-right: var(--inv-color, #13509c) 1px solid;
+        label {
+          width: 95px;
+          min-width: 95px;
+        }
+      }
+      .inv-notice {
+        .inv-content {
+          padding-top: 45px;
+        }
+        label {
+          width: 75px;
+          min-width: 75px;
+        }
+      }
+    }
+
+    .inv-details {
+      border-top: var(--inv-color, #13509c) 1px solid;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+    }
+  }
+  .inv-tail {
+    display: flex;
+    padding-top: 10px;
+    margin-right: 30px;
+    .mk-input {
+      display: flex;
+      flex: 1;
+      label {
+        width: 40%;
+        color: rgba(0, 0, 0, 0.85);
+      }
+      span {
+        width: 40%;
+        flex: none;
+      }
+    }
+  }
+
+  .detail-wrap {
+    position: relative;
+  
+    .mk-th, .mk-tr, .mk-total {
+      position: relative;
+      display: flex;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+  
+      .mk-td {
+        width: 10%;
+        height: 40px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding: 0 3px;
+        position: relative;
+      }
+      .mk-td:not(:last-child) {
+        border-right: var(--inv-color, #13509c) 1px solid;
+      }
+      .mk-td:first-child {
+        width: 20%;
+      }
+      .mk-td:nth-child(2), .mk-td:nth-child(6) {
+        width: 15%;
+      }
+  
+      .mk-left {
+        justify-content: start;
+      }
+      .mk-right {
+        justify-content: end;
+      }
+      .anticon-ellipsis {
+        padding: 0 10px;
+        position: absolute;
+        right: 0;
+      }
+    }
+    .mk-tr.active, .mk-tr:hover {
+      background: var(--mk-sys-color1);
+    }
+    .mk-upcase {
+      display: flex;
+  
+      .mk-td {
+        width: 40%;
+        height: 40px;
+        display: flex;
+        align-items: center;
+        padding: 0 20px;
+      }
+      .mk-td:first-child {
+        width: 20%;
+        padding: 0;
+        border-right: var(--inv-color, #13509c) 1px solid;
+        justify-content: center;
+      }
+      .mk-td:last-child {
+        justify-content: end;
+      }
+    }
+  }
+}
+.menu-invoice-box::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.menu-invoice-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
+
+
diff --git a/src/menu/components/module/invoice/options.jsx b/src/menu/components/module/invoice/options.jsx
new file mode 100644
index 0000000..be3bc24
--- /dev/null
+++ b/src/menu/components/module/invoice/options.jsx
@@ -0,0 +1,88 @@
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export default function (wrap) {
+  let menu = window.GLOB.customMenu
+  let books = []
+  let bookids = []
+  menu.components.forEach(item => {
+    if (item.subtype === 'account') {
+      books.push({
+        value: item.uuid,
+        label: item.name
+      })
+      bookids.push(item.uuid)
+    }
+  })
+
+  const wrapForm = [
+    {
+      type: 'radio',
+      field: 'datatype',
+      label: '绫诲瀷',
+      initval: wrap.datatype || 'static',
+      required: true,
+      options: [
+        {value: 'static', label: '鏂板鍙戠エ'},
+        {value: 'dynamic', label: '鏌ョ湅鍗曟嵁'},
+      ]
+    },
+    {
+      type: 'text',
+      field: 'name',
+      label: '缁勪欢鍚嶇О',
+      initval: wrap.name || '',
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'width',
+      label: '瀹藉害',
+      initval: wrap.width || 24,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      precision: 0,
+      required: true
+    },
+    {
+      type: 'select',
+      field: 'supBook',
+      label: '璐﹀',
+      initval: wrap.supBook || '',
+      required: true,
+      options: books,
+      allowClear: true
+    },
+    {
+      type: 'text',
+      field: 'business_type',
+      label: '寮�绁ㄧ被鍨�',
+      initval: wrap.business_type || 'sell_01',
+      required: true
+    },
+    {
+      type: 'color',
+      field: 'invColor',
+      label: '鏍峰紡',
+      initval: wrap.invColor || '',
+      tooltip: '鍙戠エ缁勪欢涓竟妗嗕互鍙婃枃瀛楃殑棰滆壊銆�',
+      allowClear: true,
+      required: false
+    },
+    {
+      type: 'radio',
+      field: 'backBtn',
+      label: '杩斿洖鎸夐挳',
+      initval: wrap.backBtn || 'hide',
+      required: true,
+      options: [
+        {value: 'hide', label: '闅愯棌'},
+        {value: 'show', label: '鏄剧ず'},
+      ]
+    },
+  ]
+
+  return wrapForm
+} 
\ No newline at end of file
diff --git a/src/menu/components/module/invoice/verifycard/baseform/index.jsx b/src/menu/components/module/invoice/verifycard/baseform/index.jsx
new file mode 100644
index 0000000..27cd4c6
--- /dev/null
+++ b/src/menu/components/module/invoice/verifycard/baseform/index.jsx
@@ -0,0 +1,181 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Tooltip, Cascader } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+
+import MenuUtils from '@/utils/utils-custom.js'
+// import './index.scss'
+const { TextArea } = Input
+
+class BaseForm extends Component {
+  static propTpyes = {
+    verify: PropTypes.object,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    modules: [],
+    menulist: [],
+    appType: sessionStorage.getItem('appType')
+  }
+
+  UNSAFE_componentWillMount() {
+    const { verify } = this.props
+    let menu = window.GLOB.customMenu
+
+    let modules = MenuUtils.getSubModules(menu.components, verify.parId, '', menu.interfaces || null)
+
+    let menulist = sessionStorage.getItem('fstMenuList')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch (e) {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
+
+    this.setState({modules, menulist})
+  }
+
+  handleConfirm = () => {
+    const { verify } = this.props
+    
+    if (verify.type === 'billout') {
+      return new Promise((resolve, reject) => {
+        this.props.form.validateFieldsAndScroll((err, values) => {
+          if (!err) {
+            resolve(values)
+          }
+        })
+      })
+    } else {
+      return Promise.resolve()
+    }
+  }
+
+  // onOptionChange = (value, key) => {
+  //   const { verify } = this.props
+
+  //   let _verify = {...verify, [key]: value}
+
+  //   this.props.onChange(_verify)
+  // }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { verify } = this.props
+    const { modules, menulist, appType } = this.state
+
+    return (
+      <Form className="base-form">
+        <Row gutter={24}>
+          <Col span={8}>
+            <Form.Item label="鎸夐挳鍚嶇О">
+              <Input value={verify.label} disabled={true}/>
+            </Form.Item>
+          </Col>
+          <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="鎵ц鎴愬姛鍚庨渶瑕佸埛鏂扮殑缁勪欢銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍒锋柊缁勪欢
+              </Tooltip>
+            }>
+              {getFieldDecorator('syncComponent', {
+                initialValue: verify.syncComponent || []
+              })(
+                <Cascader allowClear={true} options={modules} expandTrigger="hover"/>
+              )}
+            </Form.Item>
+          </Col>
+          {!appType ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="鎵ц鎴愬姛鍚庨渶瑕佸埛鏂扮殑鑿滃崟銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍒锋柊鑿滃崟
+              </Tooltip>
+            }>
+              {getFieldDecorator('refreshTab', {
+                initialValue: verify.refreshTab || []
+              })(
+                <Cascader allowClear={true} options={menulist} expandTrigger="hover"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {/* <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎺ュ彛绫诲瀷
+              </Tooltip>
+            }>
+              <Radio.Group value={verify.intertype} disabled={true}>
+                <Radio value="system">绯荤粺</Radio>
+                <Radio value="custom">鑷畾涔�</Radio>
+              </Radio.Group>
+            </Form.Item>
+          </Col> */}
+          {/* {verify.type === 'billout' ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍙傛暟澶勭悊
+              </Tooltip>
+            }>
+              {getFieldDecorator('procMode', {
+                initialValue: verify.procMode || 'system',
+              })(
+                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'procMode')}}>
+                  <Radio value="system">绯荤粺鍑芥暟</Radio>
+                  <Radio value="none">鏃�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null} */}
+          {verify.type === 'billout' ? <Col span={24}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="鎺ュ彛鍦板潃闇�閫氳繃nginx杞彂锛岄粯璁ゅ湴鍧�涓� /fcc/di/output/invoice/issue銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                娴嬭瘯鍦板潃
+              </Tooltip>
+            }>
+              {getFieldDecorator('interface', {
+                initialValue: verify.interface || '/fcc/di/output/invoice/issue',
+                rules: [
+                  { required: true, message: '璇疯緭鍏ユ祴璇曞湴鍧�!' }
+                ]
+              })(
+                <TextArea rows={2}/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {verify.type === 'billout' ? <Col span={24}>
+            <Form.Item label="姝e紡鍦板潃">
+              {getFieldDecorator('proInterface', {
+                initialValue: verify.proInterface || '/fcc/di/output/invoice/issue',
+              })(
+                <TextArea rows={2}/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {verify.type === 'billout' ? <Col span={8}>
+            <Form.Item label="鍥炶皟琛ㄥ悕">
+              {getFieldDecorator('cbTable', {
+                initialValue: verify.cbTable || '',
+                rules: [
+                  { required: true, message: '璇疯緭鍏ヨ〃鍚�!' }
+                ]
+              })(
+                <Input autoComplete="off"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(BaseForm)
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/menu/components/module/invoice/verifycard/baseform/index.scss
similarity index 100%
copy from src/tabviews/zshare/actionList/shareLink/index.scss
copy to src/menu/components/module/invoice/verifycard/baseform/index.scss
diff --git a/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx b/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
new file mode 100644
index 0000000..c5cf723
--- /dev/null
+++ b/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.jsx
@@ -0,0 +1,299 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Button, Modal, Tooltip, Radio, Select, Switch, notification } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+
+import Api from '@/api'
+import { checkSQL } from '@/utils/utils-custom.js'
+import CodeMirror from '@/templates/zshare/codemirror'
+// import './index.scss'
+
+class CustomForm extends Component {
+  static propTpyes = {
+    systemScripts: PropTypes.array,
+    customScripts: PropTypes.array,
+    scriptsChange: PropTypes.func
+  }
+
+  state = {
+    editItem: null,
+    loading: false,
+    skip: false
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    if (this.props.type) {
+      this.props.form.setFieldsValue({
+        sql: record.sql
+      })
+    } else {
+      this.props.form.setFieldsValue({
+        sql: record.sql,
+        position: record.position || 'back'
+      })
+    }
+  }
+
+  handleConfirm = () => {
+    const { type } = this.props
+    const { editItem, skip } = this.state
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (type === 'fullscreen' && err) {
+        notification.warning({
+          top: 92,
+          message: '璇疯緭鍏ql!',
+          duration: 5
+        })
+        return
+      }
+
+      if (!err) {
+        if (/^[\s\n]+$/.test(values.sql)) {
+          notification.warning({
+            top: 92,
+            message: '璇疯緭鍏ql!',
+            duration: 5
+          })
+          return
+        }
+
+        values.uuid = editItem ? editItem.uuid : ''
+        values.position = values.position || (editItem ? editItem.position : 'front')
+
+        if (type === 'fullscreen' && editItem) {
+          values.status = editItem.status || 'true'
+        }
+
+        let pass = checkSQL(values.sql, 'customscript')
+
+        if (!pass) return
+
+        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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
+          
+          Select @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address='', @ErrorCode='', @retmsg='', @account_id='', @account_year_id='', @account_code='', @account_year_code='', @bid=''
+
+        `
+
+        let _prevCustomScript = '' // 榛樿sql鍓嶆墽琛岃剼鏈�
+        let _backCustomScript = '' // 榛樿sql鍚庢墽琛岃剼鏈�
+
+        this.props.customScripts.forEach(item => {
+          if (item.status === 'false') return
+
+          if (item.position === 'front') {
+            _prevCustomScript += `
+            /* 榛樿sql鍓嶈剼鏈� */
+            ${values.uuid === item.uuid ? values.sql : item.sql}
+            `
+          } else {
+            _backCustomScript += `
+            /* 榛樿sql鍚庤剼鏈� */
+            ${values.uuid === item.uuid ? values.sql : item.sql}
+            `
+          }
+        })
+
+        if (!values.uuid) {
+          if (values.position === 'front') {
+            _prevCustomScript += `
+            /* 榛樿sql鍓嶈剼鏈� */
+            ${values.sql}
+            `
+          } else {
+            _backCustomScript += `
+            /* 榛樿sql鍚庤剼鏈� */
+            ${values.sql}
+            `
+          }
+        }
+
+        sql += _prevCustomScript + _backCustomScript
+        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 (skip) {
+          this.setState({
+            skip: false,
+            editItem: null
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.sDebug(sql).then(res => {
+            if (res.status || res.ErrCode === '-2') {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
+      }
+    })
+  }
+
+  handleCancel = () => {
+    this.setState({
+      editItem: null
+    })
+
+    this.props.form.setFieldsValue({
+      sql: ' '
+    })
+  }
+
+  selectScript = (value, option) => {
+    if (!value || !option) return
+    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, cbTable } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { editItem, skip } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form">
+        <Row gutter={24}>
+          {!type ? <Col span={8}>
+            <Form.Item label="鍥炶皟琛ㄥ悕" style={{margin: 0, whiteSpace: 'nowrap'}}>
+              {cbTable || ''}
+            </Form.Item>
+          </Col> : null}
+          {!type ? <Col span={8}>
+            <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+            </Form.Item>
+          </Col> : null}
+          {!type ? <Col span={24} className="sqlfield">
+            <Form.Item label="鍙敤瀛楁">
+              <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={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><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;
+            </Form.Item>
+          </Col> : null}
+          {!type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
+            <Form.Item style={{marginBottom: 0}} label={
+              <Tooltip placement="bottomLeft" title={'鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�'}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎵ц浣嶇疆
+              </Tooltip>
+            }>
+              {getFieldDecorator('position', {
+                initialValue: 'front'
+              })(
+                <Radio.Group>
+                  <Radio value="front">sql鍓�</Radio>
+                  <Radio value="back">sql鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {!type ? <Col span={8}>
+            <Form.Item label="蹇嵎娣诲姞" style={{marginBottom: 0}}>
+              <Select
+                showSearch
+                dropdownMatchSelectWidth={false}
+                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>
+                )}
+              </Select>
+            </Form.Item>
+          </Col> : null}
+          <Col span={5} className="add" style={{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={
+              <Tooltip placement="bottomLeft" title="鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                sql
+              </Tooltip>
+            }>
+              {getFieldDecorator('sql', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: '璇疯緭鍏ql!'
+                  }
+                ]
+              })(<CodeMirror />)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/menu/components/module/invoice/verifycard/callbackcustomscript/index.scss
similarity index 100%
copy from src/tabviews/zshare/actionList/shareLink/index.scss
copy to src/menu/components/module/invoice/verifycard/callbackcustomscript/index.scss
diff --git a/src/menu/components/module/invoice/verifycard/customscript/index.jsx b/src/menu/components/module/invoice/verifycard/customscript/index.jsx
new file mode 100644
index 0000000..c9a1299
--- /dev/null
+++ b/src/menu/components/module/invoice/verifycard/customscript/index.jsx
@@ -0,0 +1,284 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Button, notification, Modal, Tooltip, Select, Switch } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+
+import Api from '@/api'
+import { checkSQL } from '@/utils/utils-custom.js'
+import CodeMirror from '@/templates/zshare/codemirror'
+// import './index.scss'
+
+class CustomForm extends Component {
+  static propTpyes = {
+    type: PropTypes.any,
+    systemScripts: PropTypes.array,
+    customScripts: PropTypes.array,
+    scriptsChange: PropTypes.func
+  }
+
+  state = {
+    editItem: null,
+    loading: false,
+    skip: false
+  }
+
+  edit = (record) => {
+    this.setState({
+      editItem: record
+    })
+
+    this.props.form.setFieldsValue({
+      sql: record.sql
+    })
+  }
+
+  handleConfirm = () => {
+    const { type } = this.props
+    const { editItem, skip } = this.state
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (type === 'fullscreen' && err) {
+        notification.warning({
+          top: 92,
+          message: '璇疯緭鍏ql!',
+          duration: 5
+        })
+        return
+      }
+      if (!err) {
+        if (/^[\s\n]+$/.test(values.sql)) {
+          notification.warning({
+            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 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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
+          
+          Select @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address='', @ErrorCode='', @retmsg='', @account_id='', @account_year_id='', @account_code='', @account_year_code='', @bid=''
+          
+          /* 鍙戠エ涓昏〃瀛楁 */
+          
+          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='', @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='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
+          
+          /* 鍙戠エ鏄庣粏涓存椂琛� */
+          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)
+          
+          Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
+
+        `
+
+        this.props.customScripts.forEach(item => {
+          let _item = values.uuid === item.uuid ? values : item
+
+          if (_item.status === 'false') return
+
+          sql += `
+          ${_item.sql}
+          `
+        })
+
+        if (!values.uuid) {
+          sql += `
+          ${values.sql}
+          `
+        }
+
+        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 (skip) {
+          this.setState({
+            skip: false,
+            editItem: null
+          }, () => {
+            this.props.scriptsChange(values)
+          })
+          this.props.form.setFieldsValue({
+            sql: ' '
+          })
+        } else {
+          this.setState({loading: true})
+          Api.sDebug(sql).then(res => {
+            if (res.status || res.ErrCode === '-2') {
+              this.setState({
+                loading: false,
+                editItem: null
+              }, () => {
+                this.props.scriptsChange(values)
+              })
+              this.props.form.setFieldsValue({
+                sql: ' '
+              })
+            } else {
+              this.setState({loading: false})
+  
+              Modal.error({
+                title: res.message
+              })
+            }
+          })
+        }
+      }
+    })
+  }
+
+  handleCancel = () => {
+    this.setState({
+      editItem: null
+    })
+
+    this.props.form.setFieldsValue({
+      sql: ' '
+    })
+  }
+
+  selectScript = (value, option) => {
+    if (!value || !option) return
+
+    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 { getFieldDecorator } = this.props.form
+    const { editItem, skip } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} className="verify-form">
+        <Row gutter={24}>
+          {!type ? <Col span={8}>
+            <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+            </Form.Item>
+          </Col> : null}
+          {!type ? <Col span={24} className="sqlfield">
+            <Form.Item label={'鍙敤瀛楁'}>
+              <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="绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��"><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="璐﹀瀛楁锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��"><span style={{color: '#13c2c2'}}>account_id, account_year_id, account_code, account_year_code </span></Tooltip>,&nbsp;
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="涓昏〃瀛楁锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��"><span style={{color: '#8E44AD'}}>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, payee, reviewer, drawer, io, orgcode, total_net_amount, total_tax, total_amount, business_type</span></Tooltip>,&nbsp;
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="瀛愯〃瀛楁锛堝晢鍝佹槑缁嗭級锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��">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</Tooltip>
+            </Form.Item>
+          </Col> : null}
+          {/* {!_type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
+            <Form.Item style={{marginBottom: 0}} label={
+              <Tooltip placement="bottomLeft" title="鑷畾涔夎剼鏈笌榛樿sql浣嶇疆鍏崇郴銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎵ц浣嶇疆
+              </Tooltip>
+            }>
+              {getFieldDecorator('position', {
+                initialValue: 'front'
+              })(
+                <Radio.Group>
+                  <Radio value="init">鍒濆鍖�</Radio>
+                  <Radio value="front">sql鍓�</Radio>
+                  <Radio value="back">sql鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null} */}
+          {!type ? <Col span={8}>
+            <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
+              <Select
+                showSearch
+                dropdownMatchSelectWidth={false}
+                filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                onSelect={this.selectScript}
+              >
+                {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={{whiteSpace: 'nowrap'}}>
+            <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginBottom: 15, marginLeft: 30}}>
+              {type === 'fullscreen' && !editItem ? '娣诲姞' : '淇濆瓨'}
+            </Button>
+            <Button onClick={this.handleCancel} style={{marginBottom: 15, marginLeft: 10}}>
+              鍙栨秷
+            </Button>
+          </Col>
+          <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={
+              <Tooltip placement="bottomLeft" title="鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                sql
+              </Tooltip>
+            }>
+              {getFieldDecorator('sql', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: '璇疯緭鍏ql!'
+                  }
+                ]
+              })(<CodeMirror />)}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/menu/components/module/invoice/verifycard/customscript/index.scss
similarity index 100%
copy from src/tabviews/zshare/actionList/shareLink/index.scss
copy to src/menu/components/module/invoice/verifycard/customscript/index.scss
diff --git a/src/menu/components/module/invoice/verifycard/index.jsx b/src/menu/components/module/invoice/verifycard/index.jsx
new file mode 100644
index 0000000..19d29c5
--- /dev/null
+++ b/src/menu/components/module/invoice/verifycard/index.jsx
@@ -0,0 +1,696 @@
+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, Typography, InputNumber } from 'antd'
+import { CheckCircleOutlined, StopOutlined, EditOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
+import moment from 'moment'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import BaseForm from './baseform'
+import CustomScript from './customscript'
+import CallBackCustomScript from './callbackcustomscript'
+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 VerifyCard extends Component {
+  static propTpyes = {
+    config: PropTypes.any,
+    card: PropTypes.object,
+    columns: PropTypes.array
+  }
+
+  state = {
+    activeKey: 'base',
+    verify: {},
+    systemScripts: [],
+    scriptsColumns: [
+      {
+        title: 'SQL',
+        dataIndex: 'sql',
+        width: '70%',
+        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: 'position',
+      //   width: '10%',
+      //   render: (text, record) => {
+      //     if (record.position === 'init') {
+      //       return <span style={{color: 'orange'}}>鍒濆鍖�</span>
+      //     } else if (record.position === 'front') {
+      //       return <span style={{color: '#26C281'}}>sql鍓�</span>
+      //     } else {
+      //       return <span style={{color: '#1890ff'}}>sql鍚�</span>
+      //     }
+      //   }
+      // },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        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: (_, record) =>
+          (<div style={{textAlign: 'center'}}>
+            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
+            <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+            <Popconfirm
+              overlayClassName="popover-confirm"
+              title="纭畾鍒犻櫎鍚�?"
+              onConfirm={() => this.handleDelete(record, 'scripts')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ],
+    cbScriptsColumns: [
+      {
+        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: 'position',
+        width: '10%',
+        render: (_, record) => {
+          if (record.position === 'front') {
+            return <span style={{color: '#26C281'}}>sql鍓�</span>
+          } else {
+            return <span style={{color: '#1890ff'}}>sql鍚�</span>
+          }
+        }
+      },
+      {
+        title: '鐘舵��',
+        dataIndex: 'status',
+        width: '10%',
+        render: (_, 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: '20%',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (<div style={{textAlign: 'center'}}>
+            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record, 'cbscripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
+            <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record, 'cbscripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+            <Popconfirm
+              overlayClassName="popover-confirm"
+              title="纭畾鍒犻櫎鍚�?"
+              onConfirm={() => this.handleDelete(record, 'cbscripts')
+            }>
+              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
+            </Popconfirm>
+          </div>)
+      }
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+    const { card } = this.props
+    let _verify = fromJS(card).toJS()
+
+    // _verify.intertype = _verify.intertype || 'system'
+    _verify.scripts = _verify.scripts || []
+    _verify.cbScripts = _verify.cbScripts || []
+
+    _verify.scripts.forEach((item, i) => {
+      item.$index = i + 1
+    })
+    _verify.cbScripts.forEach((item, i) => {
+      item.$index = i + 1
+    })
+
+    this.setState({
+      activeKey: 'base',
+      verify: _verify,
+      oriVerify: fromJS(_verify).toJS()
+    })
+  }
+
+  componentDidMount() {
+    let mutilForms = [
+      {
+        obj_name: 'scripts',
+        arr_field: 'funcname,longparam',
+        LText: window.btoa(window.encodeURIComponent(`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`))
+      }
+    ]
+
+    mutilForms = mutilForms.map(item => `select '${item.obj_name}' as obj_name,'${item.arr_field}' as arr_field,'${item.LText}' as LText`)
+
+    let mutilparam = {
+      func: 'sPC_Get_SelectedList',
+      LText: mutilForms.join(' union all '),
+      obj_name: '',
+      arr_field: '',
+      table_type: 'Y',
+      exec_type: 'x'
+    }
+
+    mutilparam.LText = Utils.formatOptions(mutilparam.LText, 'x')
+    mutilparam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    mutilparam.secretkey = Utils.encrypt('', mutilparam.timestamp)
+    mutilparam.open_key = Utils.encryptOpenKey(mutilparam.secretkey, mutilparam.timestamp)
+
+    if (window.GLOB.cloudServiceApi) { // 浜戠璇锋眰
+      mutilparam.rduri = window.GLOB.cloudServiceApi
+      mutilparam.userid = sessionStorage.getItem('CloudUserID') || ''
+      mutilparam.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
+    }
+
+    Api.getSystemCacheConfig(mutilparam).then(res => {
+      if (res.status) {
+        this.setState({
+          systemScripts: res.scripts.map(item => {
+            return {
+              name: item.funcname,
+              value: window.decodeURIComponent(window.atob(item.longparam))
+            }
+          })
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  scriptsChange = (values) => {
+    let verify = fromJS(this.state.verify).toJS()
+
+    if (values.uuid) {
+      verify.scripts = verify.scripts.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.scripts.push(values)
+    }
+
+    MKEmitter.emit('editLineId', values.uuid)
+
+    this.setState({ verify })
+  }
+
+  cbScriptsChange = (values) => {
+    let verify = fromJS(this.state.verify).toJS()
+
+    if (values.uuid) {
+      verify.cbScripts = verify.cbScripts.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      verify.cbScripts.push(values)
+    }
+
+    MKEmitter.emit('editLineId', values.uuid)
+
+    this.setState({ verify })
+  }
+
+  handleDelete = (record, type) => {
+    const { verify } = this.state
+
+    if (type === 'scripts') {
+      verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
+    } else if (type === 'cbscripts') {
+      verify.cbScripts = verify.cbScripts.filter(item => item.uuid !== record.uuid)
+    }
+
+    this.setState({ verify })
+  }
+
+  handleEdit = (record, type) => {
+    let node = null
+
+    if (type === 'scripts') {
+      this.scriptsForm.edit(record)
+      node = document.getElementById('mk-normal-script')
+    } else if (type === 'cbscripts') {
+      this.cbscriptsForm.edit(record)
+      node = document.getElementById('mk-callback-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, type) => {
+    let verify = fromJS(this.state.verify).toJS()
+    record.status = record.status === 'false' ? 'true' : 'false'
+
+    if (type === 'scripts') {
+      verify.scripts = verify.scripts.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    } else if (type === 'cbscripts') {
+      verify.cbScripts = verify.cbScripts.map(item => {
+        if (item.uuid === record.uuid) {
+          return record
+        } else {
+          return item
+        }
+      })
+    }
+
+    this.setState({ verify })
+  }
+
+  showError = (errorType) => {
+    const { verify } = this.state
+
+    if (errorType === 'S') {
+      let time = verify.stime || 2
+      notification.success({
+        top: 92,
+        message: '鎵ц鎴愬姛锛�',
+        duration: time
+      })
+    } else if (errorType === 'Y') {
+      Modal.success({
+        title: '鎵ц鎴愬姛锛�'
+      })
+    } else if (errorType === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: verify.ftime || 10
+      })
+    } else if (errorType === 'N') {
+      notification.error({
+        top: 92,
+        message: '鎵ц澶辫触锛�',
+        duration: verify.ntime || 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}
+    })
+  }
+
+  handleConfirm = () => {
+    const { activeKey } = this.state
+    let verify = fromJS(this.state.verify).toJS()
+
+    let msg = ''
+    if (this.scriptsForm && this.scriptsForm.state.editItem) {
+      msg = '鍓嶇疆鑴氭湰'
+    } else if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
+      msg = '鍓嶇疆鑴氭湰'
+    } else if (this.cbscriptsForm && this.cbscriptsForm.state.editItem) {
+      msg = '鍥炶皟鑴氭湰'
+    } else if (this.cbscriptsForm && this.cbscriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbscriptsForm.props.form.getFieldValue('sql'))) {
+      msg = '鍥炶皟鑴氭湰'
+    }
+
+    return new Promise((resolve, reject) => {
+      if (activeKey === 'base' && verify.type === 'billout') {
+        this.baseForm.handleConfirm().then(res => {
+          let _verify = {...verify, ...res}
+          
+          if (msg) {
+            confirm({
+              content: msg + '鏈繚瀛橈紝纭畾鎻愪氦鍚楋紵',
+              onOk() {
+                resolve(_verify)
+              },
+              onCancel() {}
+            })
+          } else {
+            resolve(_verify)
+          }
+        })
+      } else {
+        if (msg) {
+          confirm({
+            content: msg + '鏈繚瀛橈紝纭畾鎻愪氦鍚楋紵',
+            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()
+      }
+    })
+  }
+
+  changeTab = (val) => {
+    const { activeKey, verify } = this.state
+
+    if (activeKey === 'base') {
+      this.baseForm.handleConfirm().then(res => {
+        this.setState({
+          verify: {...verify, ...res},
+          activeKey: val
+        })
+      })
+    } else {
+      this.setState({
+        activeKey: val
+      })
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { card, columns } = this.props
+    const { activeKey, verify, scriptsColumns, cbScriptsColumns } = this.state
+    
+    return (
+      <div>
+        <div className="mk-com-name">{card.label}</div>
+        <Tabs activeKey={activeKey} className="mk-invoice-tabs" onChange={this.changeTab}>
+          <TabPane tab="鍩虹璁剧疆" key="base">
+            <BaseForm columns={columns} verify={verify} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
+          </TabPane>
+          <TabPane tab={
+            <span>
+              鍓嶇疆鑴氭湰
+              {verify.scripts.length ? <span className="count-tip">{verify.scripts.length}</span> : null}
+            </span>
+          } key="scripts" id="mk-normal-script">
+            <FullScripts
+              scripts={verify.scripts}
+              getScriptsFullForm={() => this.scriptsFullForm}
+              getScriptsForm={() => this.scriptsForm}
+              handleStatus={this.handleStatus}
+              handleDelete={this.handleDelete}
+            >
+              <CustomScript
+                type="fullscreen"
+                customScripts={verify.scripts}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.scriptsChange}
+                wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
+              />
+            </FullScripts>
+            <CustomScript
+              customScripts={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>
+          {card.type === 'billout' ? <TabPane tab={
+            <span>
+              鍥炶皟鑴氭湰
+              {verify.cbScripts.length ? <span className="count-tip">{verify.cbScripts.length}</span> : null}
+            </span>
+          } key="cbScripts" id="mk-callback-script">
+            <FullScripts
+              scripts={verify.cbScripts}
+              getScriptsFullForm={() => this.cbscriptsFullForm}
+              getScriptsForm={() => this.cbscriptsForm}
+              handleStatus={(item) => this.handleStatus(item, 'cbscripts')}
+              handleDelete={(item) => this.handleDelete(item, 'cbscripts')}
+            >
+              <CallBackCustomScript
+                type="fullscreen"
+                cbTable={verify.cbTable}
+                customScripts={verify.cbScripts}
+                systemScripts={this.state.systemScripts}
+                scriptsChange={this.cbScriptsChange}
+                wrappedComponentRef={(inst) => this.cbscriptsFullForm = inst}
+              />
+            </FullScripts>
+            <CallBackCustomScript
+              cbTable={verify.cbTable}
+              customScripts={verify.cbScripts}
+              systemScripts={this.state.systemScripts}
+              scriptsChange={this.cbScriptsChange}
+              wrappedComponentRef={(inst) => this.cbscriptsForm = inst}
+            />
+            <EditTable actions={['move']} data={verify.cbScripts} columns={cbScriptsColumns} onChange={(cbScripts) => {this.setState({verify: {...verify, cbScripts}})}}/>
+          </TabPane> : null}
+          <TabPane tab="sql绀轰緥" key="sql">
+            <div className="mk-sql-wrap">
+              <p className="note">{`/* 绯荤粺瀛楁 */`}</p>
+              <p>
+                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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
+              </p>
+              <p>
+                Select @UserName='', @FullName='', @RoleID='', @mk_departmentcode='', @mk_organization='', @mk_user_type='', @mk_nation='', @mk_province='', @mk_city='', @mk_district='', @mk_address='', @ErrorCode='', @retmsg='', @account_id='', @account_year_id='', @account_code='', @account_year_code='', @bid=''
+              </p>
+              <p className="note">{`/* 鍙戠エ涓昏〃瀛楁 */`}</p>
+              <p>
+                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)
+              </p>
+              <p>
+                Select @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='', @payee='', @reviewer='', @drawer='', @io='', @orgcode='', @total_net_amount=0, @total_tax=0, @total_amount=0, @business_type='sell_01'
+              </p>
+              <p className="note">{`/* 鍙戠エ鏄庣粏涓存椂琛� */`}</p>
+              <p>
+                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))
+              </p>
+              <p>
+                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)
+              </p>
+              <p>
+                Select '', '', '', '', 0, 0, 0, '', '', 0, 0, '', '', '', '', '', '', ''
+              </p>
+              <p className="note">{`/* 鍓嶇疆鑴氭湰 */`}</p>
+              <p>
+                ......
+              </p>
+              {card.type === 'billout' ? <p>
+                aaa: if @ErrorCode!=''
+                insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,''
+              </p> :
+              <p>
+                aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg
+              </p>}
+            </div>
+          </TabPane>
+          <TabPane tab="淇℃伅鎻愮ず" key="tip">
+            <Form className="tip-form">
+              <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()(VerifyCard)
\ No newline at end of file
diff --git a/src/menu/components/module/invoice/verifycard/index.scss b/src/menu/components/module/invoice/verifycard/index.scss
new file mode 100644
index 0000000..c05f0e1
--- /dev/null
+++ b/src/menu/components/module/invoice/verifycard/index.scss
@@ -0,0 +1,124 @@
+.mk-invoice-tabs {
+  .ant-tabs-nav .ant-tabs-tab {
+    margin-right: 25px;
+  }
+  .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;
+  }
+  .ant-input-disabled {
+    color: rgba(0, 0, 0, 0.85);
+    background-color: #ffffff;
+    cursor: text;
+  }
+  .ant-radio-disabled + span {
+    color: rgba(0, 0, 0, 0.85);
+  }
+  .base-form {
+    padding-right: 50px;
+    .ant-form-item {
+      display: flex;
+      .ant-form-item-control-wrapper {
+        flex: 1;
+      }
+    }
+    .ant-col-8 {
+      .ant-form-item-label {
+        width: 33.33%;
+      }
+    }
+    .ant-col-24 {
+      .ant-form-item-label {
+        width: 10.8%;
+      }
+    }
+  }
+  .tip-form {
+    .ant-form-item {
+      display: flex;
+    }
+  }
+  .mk-sql-wrap {
+    color: rgba(0, 0, 0, 0.85);
+    .note {
+      margin-bottom: 0px;
+    }
+  }
+  .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%;
+      }
+    }
+    .add {
+      padding-top: 4px;
+
+      .mk-green {
+        margin-bottom: 15px;
+      }
+    }
+  }
+  .custom-table .ant-empty {
+    margin: 20px 8px!important;
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+  .operation-btn:not(:first-child) {
+    margin-left: 5px;
+  }
+  .full-scripts {
+    position: absolute;
+    right: 24px;
+    top: 0px;
+    font-size: 16px;
+    color: #1890ff;
+    z-index: 1;
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/module/voucher/index.jsx b/src/menu/components/module/voucher/index.jsx
index 905ef23..4d26cc9 100644
--- a/src/menu/components/module/voucher/index.jsx
+++ b/src/menu/components/module/voucher/index.jsx
@@ -122,16 +122,17 @@
           <ToolOutlined />
         </Popover>
         <div className="voucher-box">
-          {card.wrap.type === 'createVoucher' ? <div className="voucher-header">
-            <Button className="add-background header-btn">淇濆瓨骞舵柊澧�</Button>
-            <Button className="add-background header-btn">淇濆瓨</Button>
-            <Button className="print-background header-btn">鎵撳嵃</Button>
-            <Button className="out-background header-btn">鏇村</Button>
+          {card.wrap.type === 'createVoucher' ? <div className="voucher-header" style={{padding: `10px ${card.wrap.space || 0}px`}}>
+            <Button>淇濆瓨骞舵柊澧�</Button>
+            <Button>淇濆瓨</Button>
+            <Button>鎵撳嵃</Button>
+            <Button>鏇村</Button>
           </div> : null}
-          {card.wrap.type === 'checkVoucher' ? <div className="voucher-header">
-            <Button className="add-background header-btn">淇濆瓨</Button>
-            <Button className="print-background header-btn">鎵撳嵃</Button>
-            <Button className="out-background header-btn">鍏抽棴</Button>
+          {card.wrap.type === 'checkVoucher' ? <div className="voucher-header" style={{padding: `10px ${card.wrap.space || 0}px`}}>
+            <Button>淇濆瓨</Button>
+            <Button>鎵撳嵃</Button>
+            <Button>瀹℃牳</Button>
+            <Button>鍏抽棴</Button>
           </div> : null}
           <div className="voucher-body" style={{padding: `0px ${card.wrap.space || 0}px`}}>
             {card.wrap.type === 'createVoucher' || card.wrap.type === 'checkVoucher' ? <div className="pre-wrap">
@@ -158,8 +159,8 @@
                 妯℃澘绫诲瀷:
                 <div>鏃ュ父鏀嚭<DownOutlined/></div>
               </div>
-              <Button className="close-temp header-btn">鍏抽棴</Button>
-              <Button className="save-temp header-btn">淇濆瓨</Button>
+              <Button>鍏抽棴</Button>
+              <Button>淇濆瓨</Button>
             </div> : null}
             <VoucherTable config={card}/>
             {card.wrap.type === 'createVoucher' || card.wrap.type === 'checkVoucher' ? <div className="user">鍒跺崟浜猴細</div> : null}
diff --git a/src/menu/components/module/voucher/index.scss b/src/menu/components/module/voucher/index.scss
index 964fd36..9f43cfe 100644
--- a/src/menu/components/module/voucher/index.scss
+++ b/src/menu/components/module/voucher/index.scss
@@ -24,10 +24,13 @@
     padding: 10px;
     border-bottom: 1px solid #eeeeee;
 
-    .header-btn {
+    .ant-btn {
       height: 28px;
       min-width: 80px;
       margin-right: 10px;
+      background-color: #ffffff;
+      border-color: #d8d8d8;
+      color: rgba(0, 0, 0, 0.65);
     }
   }
   .voucher-body {
@@ -76,12 +79,14 @@
         }
       }
     }
-    .header-btn {
-      float: right;
-      margin-left: 10px;
-    }
     .pre-wrap {
       padding: 10px 0px;
+      >.ant-btn {
+        margin-right: 10px;
+        background-color: #ffffff;
+        border-color: #d8d8d8;
+        color: rgba(0, 0, 0, 0.65);
+      }
     }
     .voucher-date {
       display: inline-block;
@@ -117,38 +122,6 @@
     .user {
       padding-top: 15px;
     }
-  }
-
-  .add-background {
-    background: #26C281;
-    border-color: #26C281;
-    color: #ffffff;
-  }
-  .print-background {
-    background-color: #8E44AD;
-    border-color: #8E44AD;
-    color: #ffffff;
-  }
-  .out-background {
-    background-color: rgb(50, 197, 210);
-    border-color: rgb(50, 197, 210);
-    color: #ffffff;
-  }
-  .save-temp {
-    background-color: #1890ff;
-    border-color: #1890ff;
-    color: #ffffff;
-  }
-  .close-temp {
-    background-color: #ffffff;
-    border-color: #f5222d;
-    color: #f5222d;
-  }
-
-  .system-background {
-    background: #1890ff;
-    border-color: #1890ff;
-    color: #ffffff;
   }
 }
 .menu-voucher-box::after {
diff --git a/src/menu/components/module/voucher/options.jsx b/src/menu/components/module/voucher/options.jsx
index bdc8eb0..2f268e6 100644
--- a/src/menu/components/module/voucher/options.jsx
+++ b/src/menu/components/module/voucher/options.jsx
@@ -1,3 +1,4 @@
+import React from 'react'
 import MenuUtils from '@/utils/utils-custom.js'
 
 /**
@@ -56,6 +57,7 @@
         {field: 'voucherType', values: ['createVoucher', 'checkVoucher']},
         {field: 'voucherTypeText', values: ['createVoucher', 'checkVoucher']},
         {field: 'voucherSign', values: ['createVoucher', 'checkVoucher']},
+        {field: 'printTemp', values: ['createVoucher', 'checkVoucher']},
         {field: 'supModule', values: ['checkTemp', 'checkVoucher']},
         {field: 'attachStatus', values: ['createVoucher', 'checkVoucher']},
       ]
@@ -138,6 +140,26 @@
       ]
     },
     {
+      type: 'printTemps',
+      field: 'printTemp',
+      label: '鎵撳嵃妯℃澘',
+      initval: wrap.printTemp || '',
+      help: (record) => {
+        if (record.printTemp) {
+          return <span onClick={() => {
+            sessionStorage.setItem('mk-print-temp', record.printTemp)
+            window.open('#/hs')
+
+            setTimeout(() => {
+              sessionStorage.removeItem('mk-print-temp')
+            }, 50)
+          }} style={{color: '#1890ff', cursor: 'pointer', fontSize: '13px'}}>#鏌ョ湅妯℃澘</span>
+        }
+        return ''
+      },
+      required: true
+    },
+    {
       type: 'number',
       field: 'space',
       label: '鐣欑櫧',
diff --git a/src/menu/components/module/voucher/voucherTable/index.scss b/src/menu/components/module/voucher/voucherTable/index.scss
index c46fe8d..38a139c 100644
--- a/src/menu/components/module/voucher/voucherTable/index.scss
+++ b/src/menu/components/module/voucher/voucherTable/index.scss
@@ -10,9 +10,8 @@
     position: absolute;
     bottom: 10px;
   }
-  >.ant-table-wrapper {
+  .ant-table-wrapper {
     position: relative;
-    z-index: 1;
   }
   .ant-table {
     color: inherit;
diff --git a/src/menu/components/search/main-search/dragsearch/card.jsx b/src/menu/components/search/main-search/dragsearch/card.jsx
index e09f49c..6e153b6 100644
--- a/src/menu/components/search/main-search/dragsearch/card.jsx
+++ b/src/menu/components/search/main-search/dragsearch/card.jsx
@@ -118,11 +118,11 @@
     if (options.length === 0) {
       options = [{Value: '1', Text: '閫夐」1'}, {Value: '2', Text: '閫夐」2'}]
     }
-    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '36px'}}>
+    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '40px', whiteSpace: 'nowrap'}}>
       {options.map((item, i) => (<Radio key={i} value={item.Value}> {item.Text} </Radio>))}
     </Radio.Group>)
   } else if (card.type === 'check') {
-    formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
+    formItem = <Checkbox style={{lineHeight: '36px', whiteSpace: 'nowrap'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   } else if (card.type === 'range') {
     let vals = card.initval.split(',')
     formItem = (<>
diff --git a/src/menu/components/search/main-search/index.jsx b/src/menu/components/search/main-search/index.jsx
index 1f3669c..270358a 100644
--- a/src/menu/components/search/main-search/index.jsx
+++ b/src/menu/components/search/main-search/index.jsx
@@ -255,7 +255,8 @@
           sqlVerifing: true
         })
 
-        let sql = res.dataSource
+        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
 
         let rduri = ''
@@ -354,9 +355,9 @@
   }
 
   getWrapForms = () => {
-    const { wrap, action } = this.state.card
+    const { card } = this.state
 
-    return getWrapForm(wrap, action)
+    return getWrapForm(card.wrap, card.uuid)
   }
 
   updateWrap = (res) => {
diff --git a/src/menu/components/search/main-search/options.jsx b/src/menu/components/search/main-search/options.jsx
index 8228b2b..2ed6c06 100644
--- a/src/menu/components/search/main-search/options.jsx
+++ b/src/menu/components/search/main-search/options.jsx
@@ -1,7 +1,8 @@
+import MenuUtils from '@/utils/utils-custom.js'
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
-export default function (wrap, action = []) {
+export default function (wrap, uuid) {
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
 
@@ -14,6 +15,9 @@
   } else {
     roleList = []
   }
+
+  let menu = window.GLOB.customMenu
+  let modules = MenuUtils.getSupModules(menu.components, uuid, menu.interfaces)
 
   const wrapForm = [
     {
@@ -168,6 +172,15 @@
       forbid: !!appType
     },
     {
+      type: 'cascader',
+      field: 'supModule',
+      label: '涓婄骇缁勪欢',
+      initval: wrap.supModule || [],
+      required: false,
+      options: modules,
+      forbid: sessionStorage.getItem('editMenuType') === 'popview'
+    },
+    {
       type: 'multiselect',
       field: 'blacklist',
       label: '榛戝悕鍗�',
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index 72c1ce9..c00ec97 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, Tooltip, InputNumber, Cascader, Checkbox, notification } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 import { formRule } from '@/utils/option.js'
 
@@ -12,17 +12,18 @@
 
 const { TextArea } = Input
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
+const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
 const MKTable = asyncComponent(() => import('@/components/normalform/modalform/mkTable'))
 const acTyOptions = {
-  pop: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hoverTitle', 'hidden', 'preButton', 'formCache'],
-  prompt: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'position', 'tipTitle', 'hoverTitle', 'hidden', 'preButton', 'formCache'],
-  exec: ['label', 'OpenType', 'intertype', 'Ot', 'show', 'swipe', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'anchors', 'width', 'openmenu', 'refreshTab', 'hoverTitle', 'hidden', 'preButton', 'formCache'],
-  excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'color', 'sheet', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'width', 'hidden'],
-  excelOut: ['label', 'Ot', 'OpenType', 'intertype', 'show', 'icon', 'class', 'color', 'execSuccess', 'execError', 'syncComponent', 'switchTab', 'pagination', 'search', 'width', 'hidden'],
-  popview: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'color', 'popClose', 'width', 'display', 'ratio', 'syncComponent', 'clickouter', 'maskStyle', 'closeButton', 'hidden'],
-  tab: ['label', 'Ot', 'OpenType', 'show', 'icon', 'class', 'color', 'linkmenu', 'width', 'hidden', 'openTab'],
-  innerpage: ['label', 'Ot', 'OpenType', 'pageTemplate', 'show', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
-  funcbutton: ['label', 'OpenType', 'funcType', 'show', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
+  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'],
+  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'],
+  funcbutton: ['label', 'OpenType', 'funcType', 'show', 'hover', 'swipe', 'icon', 'class', 'color', 'width', 'hidden'],
   form: ['label', 'OpenType', 'formType', 'intertype', 'Ot', 'execSuccess', 'execError', 'syncComponent', 'width', 'openmenu', 'refreshTab', 'title', 'hidden']
 }
 
@@ -160,7 +161,7 @@
     let reRequired = {}
     let reReadonly = {}
 
-    if (openType === 'pop' || openType === 'prompt' || openType === 'exec') {
+    if (['pop', 'prompt', 'exec'].includes(openType)) {
       let intertype = this.record.intertype
 
       reOptions.intertype = this.state.interTypeOptions
@@ -214,7 +215,7 @@
           shows.push('exInterface', 'exProInterface')
         }
       } else if (intertype === 'inner') {
-        shows.push('innerFunc', 'output', 'recordUser')
+        shows.push('innerFunc', 'output', 'extraParam')
         if (Ot === 'requiredOnce') { // 鍓嶇疆鍑芥暟
           shows.push('preFunc')
         }
@@ -295,7 +296,7 @@
           shows.push('exInterface', 'exProInterface')
         }
       } else if (intertype === 'inner') {
-        shows.push('innerFunc', 'recordUser')
+        shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
       } else {
         shows.push('sql', 'sqlType')
@@ -346,7 +347,7 @@
           shows.push('exInterface', 'exProInterface')
         }
       } else if (this.record.intertype === 'inner') {
-        shows.push('innerFunc', 'recordUser')
+        shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
       }
       if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
@@ -381,7 +382,7 @@
           shows.push('exInterface', 'exProInterface')
         }
       } else if (this.record.intertype === 'inner') {
-        shows.push('innerFunc', 'recordUser')
+        shows.push('innerFunc', 'extraParam')
         reRequired.innerFunc = true
       }
       if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
@@ -408,24 +409,33 @@
     } else if (openType === 'tab') {
       reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl', 'requiredOnce'].includes(op.value))
 
+      if (Ot === 'notRequired') {
+        shows.push('sysId')
+      }
+
+      if (shows.includes('linkmenu') && this.record.linkmenu[0] === 'multiMenu') {
+        shows.push('multiMenus')
+      } else if (Ot === 'notRequired' && this.record.sysId === 'js') {
+        shows.push('sign')
+      }
+
       reRequired.linkmenu = true
       reTooltip.linkmenu = ''
     } else if (openType === 'innerpage') {
       reOptions.Ot = requireOptions.filter(op => ['notRequired', 'requiredSgl'].includes(op.value))
 
       if (this.record.pageTemplate === 'custom') {
-        shows.push('url', 'proUrl', 'joint', 'open')
+        shows.push('url', 'proUrl', 'open')
       } else if (this.record.pageTemplate === 'linkpage') {
         shows.push('linkmenu', 'open')
-
-        if (Ot === 'requiredSgl') {
-          shows.push('joint')
-        }
 
         reRequired.linkmenu = true
         reTooltip.linkmenu = ''
       } else if (this.record.pageTemplate === 'billprint') {
-        shows.push('printTemp')
+        shows.push('printTemp', 'preHandle')
+        if (this.record.preHandle === 'true') {
+          shows.push('pre_func')
+        }
         reOptions.Ot = requireOptions
       } else if (this.record.pageTemplate === 'pay') {
         reOptions.Ot = requireOptions.filter(op => op.value === 'requiredSgl')
@@ -459,7 +469,7 @@
             shows.push('exInterface', 'exProInterface')
           }
         } else if (this.record.intertype === 'inner') {
-          shows.push('innerFunc', 'recordUser')
+          shows.push('innerFunc', 'extraParam')
           reRequired.innerFunc = true
         }
         if (this.record.execSuccess === 'grid' || this.record.execError === 'grid') {
@@ -503,7 +513,7 @@
         }
         reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
       } else if (_funcType === 'refund') {
-        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu')
+        shows.push('Ot', 'execSuccess', 'execError', 'syncComponent', 'openmenu', 'tipTitle')
         reOptions.Ot = requireOptions.filter(op => ['requiredSgl'].includes(op.value))
       } else if (_funcType === 'shareLink') {
         shows.push('shortUrl', 'shareUrl', 'shareProUrl', 'shareTip')
@@ -554,15 +564,21 @@
         shows.push('reason')
       }
     }
-
+    
     if (shows.includes('syncComponent') && this.record.syncComponent[0] === 'multiComponent') {
       shows.push('syncComponents')
     }
-
+    
+    if (this.record.hidden !== 'true') {
+      shows.push('permission')
+    }
     if (this.record.show === 'icon') {
       reRequired.icon = true
     } else {
       reRequired.icon = false
+      if (['pop', 'prompt', 'exec', 'popview', 'tab', 'innerpage'].includes(openType)) {
+        shows.push('showName')
+      }
     }
 
     return {
@@ -582,6 +598,7 @@
    * 3銆佸垏鎹㈡爣绛剧被鍨嬶紝閲嶇疆鍙�夋爣绛�
    */
   optionChange = (key, value) => {
+    const { type } = this.props
     const { hasclass, appType, requireOptions } = this.state
 
     this.record[key] = value
@@ -616,9 +633,16 @@
         _fieldval.label = '瀵煎嚭Excel'
         _fieldval.class = 'dgreen'
         _fieldval.execSuccess = 'never'
-        _fieldval.Ot = 'requiredOnce'
         _fieldval.control = ''
-        this.record.Ot = 'requiredOnce'
+
+        if (type !== 'card') {
+          _fieldval.Ot = 'requiredOnce'
+          this.record.Ot = 'requiredOnce'
+        } else {
+          _fieldval.Ot = 'notRequired'
+          this.record.Ot = 'notRequired'
+        }
+
         this.record.label = '瀵煎嚭Excel'
         this.record.class = 'dgreen'
         this.record.execSuccess = 'never'
@@ -784,7 +808,7 @@
       let className = ''
       let content = null
       let initVal = item.initVal || ''
-      let help = item.help || ''
+      let help = item.help || null
 
       if (item.type === 'splitLine') {
         fields.push(
@@ -951,27 +975,53 @@
         ]
 
         content = <KeyInterface type={item.key === 'exInterface' ? 'develop' : 'product'}/>
+      } else if (item.type === 'codemirror') {
+        span = 24
+        className = 'codemirror'
+        rules = [
+          { required: item.readonly ? false : item.required, message: '璇疯緭鍏�' + item.label + '!' }
+        ]
+
+        content = <CodeMirror mode="text/javascript"/>
       }
 
       if (help && typeof(help) === 'function') {
         help = help(this.record)
       }
 
-      fields.push(
-        <Col span={span} key={index}>
-          <Form.Item className={className} help={help} label={item.tooltip ?
-            <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.tooltip.length > 25 ? 350 : 250 }} title={<span onClick={(e) => e.stopPropagation()}>{item.tooltip}</span>}>
-              <QuestionCircleOutlined className="mk-form-tip" />
-              {item.label}
-            </Tooltip> : item.label
-          }>
-            {getFieldDecorator(item.key, {
-              initialValue: initVal,
-              rules: rules
-            })(content)}
-          </Form.Item>
-        </Col>
-      )
+      if (help) {
+        fields.push(
+          <Col span={span} key={index}>
+            <Form.Item className={className} help={help} label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.tooltip.length > 25 ? 350 : 250 }} title={<span onClick={(e) => e.stopPropagation()}>{item.tooltip}</span>}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: initVal,
+                rules: rules
+              })(content)}
+            </Form.Item>
+          </Col>
+        )
+      } else {
+        fields.push(
+          <Col span={span} key={index}>
+            <Form.Item className={className} label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.tooltip.length > 25 ? 350 : 250 }} title={<span onClick={(e) => e.stopPropagation()}>{item.tooltip}</span>}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: initVal,
+                rules: rules
+              })(content)}
+            </Form.Item>
+          </Col>
+        )
+      }
     })
 
     return fields
@@ -988,6 +1038,15 @@
           values.modal = card.modal || null
           values.config = card.config || null
           values.$fixed = card.$fixed || false
+
+          if (['pop', 'prompt', 'exec'].includes(values.OpenType) && values.Ot === 'required' && values.execError === 'never') {
+            notification.warning({
+              top: 92,
+              message: '閫夋嫨澶氳鏃讹紝闇�璁剧疆澶辫触鍚庣殑鍒锋柊椤�!',
+              duration: 5
+            })
+            return
+          }
 
           if (card.OpenType === 'excelOut' && values.OpenType === 'excelIn') {
             values.verify = {columns: [], scripts: [], sheet: 'Sheet1', default: 'true', range: 1, uniques: []}
@@ -1078,14 +1137,32 @@
         
               let id = values.linkmenu[values.linkmenu.length - 1]
         
-              list.forEach(item => {
-                if (item.MenuID === id) {
-                  values.MenuID = id
-                  values.MenuName = item.MenuName
-                  values.MenuNo = item.MenuNo
-                  values.tabType = item.type
-                }
-              })
+              if (id !== 'multiMenu') {
+                list.forEach(item => {
+                  if (item.MenuID === id) {
+                    values.MenuID = id
+                    values.MenuName = item.MenuName
+                    values.MenuNo = item.MenuNo
+                    values.tabType = item.type
+                  }
+                })
+                delete values.multiMenus
+              } else {
+                values.multiMenus.forEach(menu => {
+                  menu.sign = menu.sign || ''
+
+                  let _id = menu.menuId[menu.menuId.length - 1]
+
+                  list.forEach(item => {
+                    if (item.MenuID === _id) {
+                      menu.MenuID = _id
+                      menu.MenuName = item.MenuName
+                      menu.MenuNo = item.MenuNo
+                      menu.tabType = item.type
+                    }
+                  })
+                })
+              }
             }
           } else if (values.OpenType === 'funcbutton' && values.funcType === 'expPdf') {
             values.Ot = 'notRequired'
@@ -1115,6 +1192,14 @@
             })
           }
 
+          if (values.extraParam) {
+            values.extraParam.forEach(n => {
+              values[n] = 'true'
+            })
+
+            delete values.extraParam
+          }
+
           resolve(values)
         } else {
           reject(err)
diff --git a/src/menu/components/share/actioncomponent/actionform/index.scss b/src/menu/components/share/actioncomponent/actionform/index.scss
index a056976..6f639c4 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.scss
+++ b/src/menu/components/share/actioncomponent/actionform/index.scss
@@ -17,6 +17,17 @@
       width: 86%;
     }
   }
+  .codemirror {
+    .ant-col-sm-7 {
+      width: 14%;
+    }
+    .ant-col-sm-17 {
+      width: 86%;
+    }
+    .ant-form-item-label {
+      opacity: 0;
+    }
+  }
   .ant-radio-group {
     white-space: nowrap;
     .ant-radio-wrapper {
diff --git a/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx b/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx
index 4ad9280..3d37897 100644
--- a/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/mkPrintTemps/index.jsx
@@ -74,6 +74,7 @@
         showSearch
         allowClear
         value={value}
+        dropdownMatchSelectWidth={false}
         filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
         onSelect={this.selectChange}
         onChange={(val) => val === undefined && this.selectChange('')}
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index 8c39bc9..8b93c3b 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -8,7 +8,7 @@
  * @param {*} setting        缁勪欢閰嶇疆
  * @param {*} usefulFields   瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈�
  */
-export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = [], side) {
+export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = [], side, position) {
   let appType = sessionStorage.getItem('appType')
   let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
   let setting = config.setting || {}
@@ -313,6 +313,29 @@
     card.formType = 'switch'
   }
 
+  let width = card.width || (card.width === 0 ? 0 : 12)
+  if (/x/.test(card.width)) {
+    width = +width.replace(/x/, '.5')
+  }
+
+  let extraParam = []
+  if (card.recordUser === 'true') {
+    extraParam.push('recordUser')
+  }
+  if (card.dataM === 'true') {
+    extraParam.push('dataM')
+  }
+
+  if (!appType) {
+    if (typeof(card.openmenu) === 'string') {
+      card.openmenu = []
+    }
+  } else {
+    if (typeof(card.openmenu) !== 'string') {
+      card.openmenu = ''
+    }
+  }
+
   let forms = [
     {
       type: 'select',
@@ -494,14 +517,14 @@
       initVal: card.linkmenu || (isApp ? '' : []),
       required: true,
       extendName: 'MenuNo',
-      options: isApp ? appMenus : menulist
+      options: isApp ? appMenus : (menulist.length ? [...menulist, {value: 'multiMenu', label: '澶氳彍鍗�'}] : [])
     },
     {
       type: 'text',
       key: 'prefix',
       label: '鍓嶇紑',
       initVal: card.prefix || '',
-      tooltip: '鎵爜淇℃伅灏嗕笌鍓嶇紑鎷兼帴鍚庢墽琛屻�傛敞锛氳烦杞彍鍗曢渶浠kbid寮�澶淬��',
+      tooltip: '鎵爜淇℃伅灏嗕笌鍓嶇紑鎷兼帴鍚庢墽琛屻�傛敞锛氳烦杞彍鍗曢渶浠kbid锛�:鎴�,锛夊紑澶达紝mkbid锛�:鎴�,锛夎烦杞悗灏嗚鍘婚櫎銆備緥濡傦細mkbid:123456 璺宠浆鍚庨〉闈ID涓� 123456銆�',
       required: false
     },
     {
@@ -509,7 +532,8 @@
       key: 'url',
       label: '椤甸潰鍦板潃',
       initVal: card.url || '',
-      tooltip: appType === '' ? '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�' : '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�' + (appType === '' ? '鍦板潃鏍煎紡涓猴細******/admin/index.html#/iframe/menuId/@loginuid@ 浼氭墦寮�鏍囩椤点��' : ''),
+      toolWidth: 350,
       required: true
     },
     {
@@ -517,7 +541,8 @@
       key: 'proUrl',
       label: '姝e紡鍦板潃',
       initVal: card.proUrl || '',
-      tooltip: appType === '' ? '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�' : '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�' + (appType === '' ? '鍦板潃鏍煎紡涓猴細******/admin/index.html#/iframe/menuId/@loginuid@ 浼氭墦寮�鏍囩椤点��' : ''),
+      toolWidth: 350,
       required: false
     },
     {
@@ -705,6 +730,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       }, 
       ...closetab,
       ...refresh]
@@ -733,6 +761,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       },
       ...refresh]
     },
@@ -751,6 +782,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       }]
     },
     {
@@ -809,10 +843,10 @@
       key: 'width',
       min: 0,
       max: 24,
-      precision: 0,
+      precision: 1,
       label: '瀹藉害',
-      initVal: card.width || (card.width === 0 ? 0 : 12),
-      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼�備负 0 鏃跺搴﹁嚜閫傚簲銆�',
+      initVal: width,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼�備负 0 鏃跺搴﹁嚜閫傚簲銆傚彲璁剧疆鍗婂垪鍗�.5銆�',
       forbid: type !== 'card',
       required: true
     },
@@ -847,6 +881,25 @@
       }, {
         value: 'link',
         text: '鏂囧瓧+鍥炬爣'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'hover',
+      label: '鎮诞鏁堟灉',
+      initVal: card.hover || '',
+      tooltip: '榧犳爣鎮诞鎸夐挳涓婃柟鏃剁殑棰滆壊鍙樺寲銆�',
+      required: false,
+      forbid: appType === 'mob',
+      options: [{
+        value: '',
+        text: '鏃�'
+      }, {
+        value: 'mk-btn-hover-bg',
+        text: '鑳屾櫙鍙樺寲'
+      }, {
+        value: 'mk-btn-hover-border',
+        text: '杈规鍙樺寲'
       }]
     },
     {
@@ -911,20 +964,6 @@
       }]
     },
     {
-      type: 'radio',
-      key: 'joint',
-      label: '鎷兼帴鍙傛暟',
-      initVal: card.joint || 'true',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
-    },
-    {
       type: 'text',
       key: 'sheet',
       label: '琛ㄥ悕',
@@ -973,24 +1012,6 @@
     },
     {
       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: 'cascader',
       key: 'refreshTab',
       label: '鍒锋柊鑿滃崟',
       initVal: card.refreshTab || [],
@@ -1013,6 +1034,24 @@
       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',
       key: 'preButton',
       label: '鍓嶇疆鎸夐挳',
@@ -1029,14 +1068,14 @@
       tooltip: '鎵ц鎴愬姛鍚庣殑杩斿洖鍊笺�傜郴缁熷嚱鏁板彲鎸囧畾杩斿洖鐨勫彉閲忥紙浠绗﹀紑澶达紝杩斿洖id鏃跺彲浣跨敤@id@锛夛紱鑷畾涔夊嚱鏁板彲鎸囧畾杩斿洖瀛楁锛堝id锛夈��',
       initVal: card.output || '',
       required: false,
-      forbid: viewType === 'popview'
+      // forbid: viewType === 'popview'
     },
     {
       type: 'text',
       key: 'tipTitle',
       label: '纭鎻愮ず',
       initVal: card.tipTitle || '',
-      tooltip: '娉細寮圭獥锛堣〃鍗曪級鍦ㄦ樉绀轰负鏄惁妗嗘椂鏈夋晥銆�',
+      tooltip: '鎻愮ず妗嗙殑纭鎻愮ず淇℃伅銆�',
       required: false
     },
     {
@@ -1047,6 +1086,20 @@
       tooltip: '榧犳爣鎮诞鍦ㄦ寜閽笂鏂规椂鐨勬彁绀轰俊鎭��',
       forbid: appType === 'mob',
       required: false
+    },
+    {
+      type: 'select',
+      key: 'showName',
+      label: '鏄剧ず鍐呭',
+      initVal: card.showName || '',
+      tooltip: '琛岀骇鎸夐挳鍙�氳繃琛屼俊鎭帶鍒舵寜閽樉绀哄唴瀹广��',
+      required: false,
+      allowClear: true,
+      forbid: position !== 'line',
+      options: columns.map(item => ({
+        value: item.field,
+        text: `${item.label}锛�${item.field}锛塦
+      }))
     },
     {
       type: 'radio',
@@ -1221,18 +1274,18 @@
       forbid: appType === 'mob'
     },
     {
-      type: 'radio',
-      key: 'recordUser',
-      label: '璁板綍鐢ㄦ埛',
-      initVal: card.recordUser || 'false',
-      tooltip: '褰撻�夋嫨鈥滄槸鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆�',
+      type: 'checkbox',
+      key: 'extraParam',
+      label: '鎵╁睍鍙傛暟',
+      initVal: extraParam,
+      tooltip: '閫夋嫨鈥滅敤鎴蜂俊鎭�濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆傞�夋嫨鈥滄暟鎹鐞嗗憳鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� dataM 锛岀鐞嗗憳鍊间负鈥淵鈥濓紝鏅�氱敤鎴蜂负绌恒��',
       required: false,
       options: [{
-        value: 'false',
-        text: '鍚�'
+        value: 'recordUser',
+        text: '鐢ㄦ埛淇℃伅'
       }, {
-        value: 'true',
-        text: '鏄�'
+        value: 'dataM',
+        text: '鏁版嵁绠$悊鍛�'
       }]
     },
     {
@@ -1282,21 +1335,21 @@
       initVal: card.reason || '',
       required: false
     },
-    {
-      type: 'radio',
-      key: 'formCache',
-      label: '琛ㄥ崟缂撳瓨',
-      initVal: card.formCache || 'false',
-      tooltip: '涓昏鐢ㄤ簬鏁版嵁淇敼鍚庯紝鏇存柊鐩稿叧琛ㄥ崟鐨勯�夐」锛屾竻绌虹紦瀛樺悗琛ㄥ崟鍐嶆鎵撳紑鏃舵暟鎹細閲嶆柊鍔犺浇銆�',
-      required: false,
-      options: [{
-        value: 'false',
-        text: '涓嶆竻绌�'
-      }, {
-        value: 'clear',
-        text: '娓呯┖'
-      }]
-    },
+    // {
+    //   type: 'radio',
+    //   key: 'formCache',
+    //   label: '琛ㄥ崟缂撳瓨',
+    //   initVal: card.formCache || 'false',
+    //   tooltip: '涓昏鐢ㄤ簬鏁版嵁淇敼鍚庯紝鏇存柊鐩稿叧琛ㄥ崟鐨勯�夐」锛屾竻绌虹紦瀛樺悗琛ㄥ崟鍐嶆鎵撳紑鏃舵暟鎹細閲嶆柊鍔犺浇銆�',
+    //   required: false,
+    //   options: [{
+    //     value: 'false',
+    //     text: '涓嶆竻绌�'
+    //   }, {
+    //     value: 'clear',
+    //     text: '娓呯┖'
+    //   }]
+    // },
     {
       type: 'radio',
       key: 'hidden',
@@ -1311,6 +1364,18 @@
         value: 'true',
         text: '鏄�'
       }]
+    },
+    {
+      type: 'radio',
+      key: 'permission',
+      label: '鏉冮檺楠岃瘉',
+      initVal: card.permission || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '缁ф壙鑿滃崟'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: viewType === 'popview'
     },
     {
       type: 'splitLine',
@@ -1457,6 +1522,90 @@
           options: modules
         }
       ]
+    },
+    {
+      type: 'radio',
+      key: 'sysId',
+      label: '鑷畾涔塈D',
+      initVal: card.sysId || '',
+      tooltip: '涓嶉�夎鎸夐挳鍙湪鍓嶇鐢熸垚ID鍊�(32浣�)锛屼綔涓哄悗缁彍鍗曠殑BID锛屽瓨鍦ㄦ爣璁版椂锛孖D鍊煎悗灏嗘嫾鎺ユ爣璁板�笺��',
+      required: false,
+      options: [{
+        value: '',
+        text: '缁勪欢BID'
+      }, {
+        value: 'js',
+        text: '鍓嶇鐢熸垚'
+      }, {
+        value: 'empty',
+        text: '绌�'
+      }]
+    },
+    {
+      type: 'text',
+      key: 'sign',
+      label: '鏍囪',
+      initVal: card.sign || '',
+      required: false
+    },
+    {
+      type: 'table',
+      key: 'multiMenus',
+      label: '鑿滃崟鍒楄〃',
+      initVal: card.multiMenus || [],
+      required: true,
+      actions: ['edit', 'del', 'add', 'move'],
+      columns: [
+        {
+          title: '鍚嶇О',
+          dataIndex: 'name',
+          inputType: 'text',
+          editable: true,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '鑿滃崟',
+          dataIndex: 'menuId',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: [{key: 'label', value: 'label', mutilLabel: 'name'}],
+          width: '30%',
+          render: (text, record) => record.label,
+          options: menulist
+        },
+        {
+          title: '鏍囪',
+          dataIndex: 'sign',
+          inputType: 'text',
+          editable: true,
+          required: false,
+          width: '20%'
+        }
+      ]
+    },
+    {
+      type: 'radio',
+      key: 'preHandle',
+      label: '鑷畾涔夎剼鏈�',
+      initVal: card.preHandle || 'false',
+      // tooltip: '闅愯棌鍚庢寜閽湪椤甸潰涓笉鏄剧ず锛屼笖涓嶅弬涓庢潈闄愬垎閰嶃��',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '绂佺敤'
+      }, {
+        value: 'true',
+        text: '鍚敤'
+      }]
+    },
+    {
+      type: 'codemirror',
+      key: 'pre_func',
+      label: '鑷畾涔夎剼鏈�',
+      initVal: card.pre_func || '',
+      required: true,
     }
   ]
 
@@ -1470,7 +1619,7 @@
  * @param {*} setting        缁勪欢閰嶇疆
  * @param {*} usefulFields   瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈�
  */
-export function getBaseTableActionForm (card, functip, config, usefulFields, modules) {
+export function getBaseTableActionForm (card, functip, config, usefulFields, modules, position) {
   let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
   let setting = config.setting || {}
   let columns = config.columns || []
@@ -1559,6 +1708,14 @@
 
   if (card.OpenType === 'form') { // 鎷栨嫿娣诲姞绫诲瀷杞崲
     card.OpenType = 'pop'
+  }
+
+  let extraParam = []
+  if (card.recordUser === 'true') {
+    extraParam.push('recordUser')
+  }
+  if (card.dataM === 'true') {
+    extraParam.push('dataM')
   }
 
   let forms = [
@@ -1721,14 +1878,15 @@
       initVal: card.linkmenu || [],
       required: true,
       extendName: 'MenuNo',
-      options: menulist
+      options: menulist.length ? [...menulist, {value: 'multiMenu', label: '澶氳彍鍗�'}] : []
     },
     {
       type: 'textarea',
       key: 'url',
       label: '椤甸潰鍦板潃',
       initVal: card.url || '',
-      tooltip: '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆傚湴鍧�鏍煎紡涓猴細******/admin/index.html#/iframe/menuId/@loginuid@ 浼氭墦寮�鏍囩椤点��',
+      toolWidth: 350,
       required: true
     },
     {
@@ -1736,7 +1894,8 @@
       key: 'proUrl',
       label: '姝e紡鍦板潃',
       initVal: card.proUrl || '',
-      tooltip: '鍦板潃鏍煎紡涓猴細http://******/admin/index.html#/iframe/menuId/loginuid/BID 浼氭墦寮�鏍囩椤点�傛敞锛氫娇鐢ˊloginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛涢�夋嫨鍗曡涓旀嫾鎺ュ弬鏁版椂浼氭嫾鎺ID銆�',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆傚湴鍧�鏍煎紡涓猴細******/admin/index.html#/iframe/menuId/@loginuid@ 浼氭墦寮�鏍囩椤点��',
+      toolWidth: 350,
       required: false
     },
     {
@@ -1922,6 +2081,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       }, 
       ...refresh]
     },
@@ -1947,6 +2109,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       },
       ...refresh]
     },
@@ -1965,6 +2130,9 @@
       }, {
         value: 'mainline',
         text: '鍒锋柊涓婄骇缁勪欢 - 琛�'
+      }, {
+        value: 'maingrid',
+        text: '鍒锋柊涓婄骇缁勪欢'
       }]
     },
     {
@@ -2063,6 +2231,24 @@
       }]
     },
     {
+      type: 'radio',
+      key: 'hover',
+      label: '鎮诞鏁堟灉',
+      initVal: card.hover || '',
+      tooltip: '榧犳爣鎮诞鎸夐挳涓婃柟鏃剁殑棰滆壊鍙樺寲銆�',
+      required: false,
+      options: [{
+        value: '',
+        text: '鏃�'
+      }, {
+        value: 'mk-btn-hover-bg',
+        text: '鑳屾櫙鍙樺寲'
+      }, {
+        value: 'mk-btn-hover-border',
+        text: '杈规鍙樺寲'
+      }]
+    },
+    {
       type: 'icon',
       key: 'icon',
       label: '鍥炬爣',
@@ -2077,20 +2263,6 @@
       initVal: card.class,
       required: false,
       options: btnClasses
-    },
-    {
-      type: 'radio',
-      key: 'joint',
-      label: '鎷兼帴鍙傛暟',
-      initVal: card.joint || 'true',
-      required: false,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
     },
     {
       type: 'text',
@@ -2166,14 +2338,14 @@
       tooltip: '鎵ц鎴愬姛鍚庣殑杩斿洖鍊笺�傜郴缁熷嚱鏁板彲鎸囧畾杩斿洖鐨勫彉閲忥紙浠绗﹀紑澶达紝杩斿洖id鏃跺彲浣跨敤@id@锛夛紱鑷畾涔夊嚱鏁板彲鎸囧畾杩斿洖瀛楁锛堝id锛夈��',
       initVal: card.output || '',
       required: false,
-      forbid: viewType === 'popview'
+      // forbid: viewType === 'popview'
     },
     {
       type: 'text',
       key: 'tipTitle',
       label: '纭鎻愮ず',
       initVal: card.tipTitle || '',
-      tooltip: '娉細寮圭獥锛堣〃鍗曪級鍦ㄦ樉绀轰负鏄惁妗嗘椂鏈夋晥銆�',
+      tooltip: '鎻愮ず妗嗙殑纭鎻愮ず淇℃伅銆�',
       required: false
     },
     {
@@ -2183,6 +2355,20 @@
       initVal: card.hoverTitle || '',
       tooltip: '榧犳爣鎮诞鍦ㄦ寜閽笂鏂规椂鐨勬彁绀轰俊鎭��',
       required: false
+    },
+    {
+      type: 'select',
+      key: 'showName',
+      label: '鏄剧ず鍐呭',
+      initVal: card.showName || '',
+      tooltip: '琛岀骇鎸夐挳鍙�氳繃琛屼俊鎭帶鍒舵寜閽樉绀哄唴瀹广��',
+      required: false,
+      allowClear: true,
+      forbid: position !== 'line',
+      options: columns.map(item => ({
+        value: item.field,
+        text: `${item.label}锛�${item.field}锛塦
+      }))
     },
     {
       type: 'radio',
@@ -2279,18 +2465,18 @@
       required: false
     },
     {
-      type: 'radio',
-      key: 'recordUser',
-      label: '璁板綍鐢ㄦ埛',
-      initVal: card.recordUser || 'false',
-      tooltip: '褰撻�夋嫨鈥滄槸鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆�',
+      type: 'checkbox',
+      key: 'extraParam',
+      label: '鎵╁睍鍙傛暟',
+      initVal: extraParam,
+      tooltip: '閫夋嫨鈥滅敤鎴蜂俊鎭�濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� username 涓� fullname銆傞�夋嫨鈥滄暟鎹鐞嗗憳鈥濇椂锛屽唴閮ㄥ嚱鏁扮殑浼犲弬浼氬鍔� dataM 锛岀鐞嗗憳鍊间负鈥淵鈥濓紝鏅�氱敤鎴蜂负绌恒��',
       required: false,
       options: [{
-        value: 'false',
-        text: '鍚�'
+        value: 'recordUser',
+        text: '鐢ㄦ埛淇℃伅'
       }, {
-        value: 'true',
-        text: '鏄�'
+        value: 'dataM',
+        text: '鏁版嵁绠$悊鍛�'
       }]
     },
     {
@@ -2340,21 +2526,21 @@
       initVal: card.reason || '',
       required: false
     },
-    {
-      type: 'radio',
-      key: 'formCache',
-      label: '琛ㄥ崟缂撳瓨',
-      initVal: card.formCache || 'false',
-      tooltip: '涓昏鐢ㄤ簬鏁版嵁淇敼鍚庯紝鏇存柊鐩稿叧琛ㄥ崟鐨勯�夐」锛屾竻绌虹紦瀛樺悗琛ㄥ崟鍐嶆鎵撳紑鏃舵暟鎹細閲嶆柊鍔犺浇銆�',
-      required: false,
-      options: [{
-        value: 'false',
-        text: '涓嶆竻绌�'
-      }, {
-        value: 'clear',
-        text: '娓呯┖'
-      }]
-    },
+    // {
+    //   type: 'radio',
+    //   key: 'formCache',
+    //   label: '琛ㄥ崟缂撳瓨',
+    //   initVal: card.formCache || 'false',
+    //   tooltip: '涓昏鐢ㄤ簬鏁版嵁淇敼鍚庯紝鏇存柊鐩稿叧琛ㄥ崟鐨勯�夐」锛屾竻绌虹紦瀛樺悗琛ㄥ崟鍐嶆鎵撳紑鏃舵暟鎹細閲嶆柊鍔犺浇銆�',
+    //   required: false,
+    //   options: [{
+    //     value: 'false',
+    //     text: '涓嶆竻绌�'
+    //   }, {
+    //     value: 'clear',
+    //     text: '娓呯┖'
+    //   }]
+    // },
     {
       type: 'radio',
       key: 'hidden',
@@ -2369,6 +2555,18 @@
         value: 'true',
         text: '鏄�'
       }]
+    },
+    {
+      type: 'radio',
+      key: 'permission',
+      label: '鏉冮檺楠岃瘉',
+      initVal: card.permission || 'true',
+      required: false,
+      options: [
+        {value: 'true', text: '鍚敤'},
+        {value: 'false', text: '绂佺敤'},
+      ],
+      forbid: viewType === 'popview'
     },
     {
       type: 'radio',
@@ -2420,6 +2618,90 @@
           options: modules
         }
       ]
+    },
+    {
+      type: 'radio',
+      key: 'sysId',
+      label: '鑷畾涔塈D',
+      initVal: card.sysId || '',
+      tooltip: '涓嶉�夎鎸夐挳鍙湪鍓嶇鐢熸垚ID鍊�(32浣�)锛屼綔涓哄悗缁彍鍗曠殑BID锛屽瓨鍦ㄦ爣璁版椂锛孖D鍊煎悗灏嗘嫾鎺ユ爣璁板�笺��',
+      required: false,
+      options: [{
+        value: '',
+        text: '缁勪欢BID'
+      }, {
+        value: 'js',
+        text: '鍓嶇鐢熸垚'
+      }, {
+        value: 'empty',
+        text: '绌�'
+      }]
+    },
+    {
+      type: 'text',
+      key: 'sign',
+      label: '鏍囪',
+      initVal: card.sign || '',
+      required: false
+    },
+    {
+      type: 'table',
+      key: 'multiMenus',
+      label: '鑿滃崟鍒楄〃',
+      initVal: card.multiMenus || [],
+      required: true,
+      actions: ['edit', 'del', 'add', 'move'],
+      columns: [
+        {
+          title: '鍚嶇О',
+          dataIndex: 'name',
+          inputType: 'text',
+          editable: true,
+          required: false,
+          width: '30%'
+        },
+        {
+          title: '鑿滃崟',
+          dataIndex: 'menuId',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: [{key: 'label', value: 'label', mutilLabel: 'name'}],
+          width: '30%',
+          render: (text, record) => record.label,
+          options: menulist
+        },
+        {
+          title: '鏍囪',
+          dataIndex: 'sign',
+          inputType: 'text',
+          editable: true,
+          required: false,
+          width: '20%'
+        }
+      ]
+    },
+    {
+      type: 'radio',
+      key: 'preHandle',
+      label: '鑷畾涔夎剼鏈�',
+      initVal: card.preHandle || 'false',
+      // tooltip: '闅愯棌鍚庢寜閽湪椤甸潰涓笉鏄剧ず锛屼笖涓嶅弬涓庢潈闄愬垎閰嶃��',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '绂佺敤'
+      }, {
+        value: 'true',
+        text: '鍚敤'
+      }]
+    },
+    {
+      type: 'codemirror',
+      key: 'pre_func',
+      label: '鑷畾涔夎剼鏈�',
+      initVal: card.pre_func || '',
+      required: true,
     }
   ]
 
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 4029b06..96a9190 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -120,7 +120,17 @@
     const { card, actionlist } = this.state
 
     let _card = fromJS(card).toJS()
-    _card.style = style
+    _card.style = fromJS(style).toJS()
+
+    if (_card.style.paddingLeft === '15px') {
+      delete _card.style.paddingLeft
+    }
+    if (_card.style.paddingRight === '15px') {
+      delete _card.style.paddingRight
+    }
+    if (_card.style.minHeight === '28px') {
+      delete _card.style.minHeight
+    }
 
     let _actionlist = actionlist.map(cell => {
       if (cell.uuid === _card.uuid) return _card
@@ -137,6 +147,10 @@
   changeBtnStyle = (element) => {
     let _style = element.style ? fromJS(element.style).toJS() : {}
     let options = ['font', 'border', 'background', 'margin', 'padding', 'minHeight']
+
+    _style.paddingLeft = _style.paddingLeft || '15px'
+    _style.paddingRight = _style.paddingRight || '15px'
+    _style.minHeight = _style.minHeight || '28px'
 
     this.setState({
       card: element
@@ -718,6 +732,7 @@
           destroyOnClose
         >
           <ActionForm
+            type={config.type === 'tree' ? 'card' : ''}
             card={card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
diff --git a/src/menu/components/share/normalheader/index.jsx b/src/menu/components/share/normalheader/index.jsx
index acc4e22..e0ed3f4 100644
--- a/src/menu/components/share/normalheader/index.jsx
+++ b/src/menu/components/share/normalheader/index.jsx
@@ -36,11 +36,22 @@
   }
 
   getStyle = (style) => {
-    if (!style.borderBottomWidth) {
-      style.borderBottomWidth = '0px'
+    let _style = fromJS(style).toJS()
+    if (!_style.borderBottomWidth) {
+      _style.borderBottomWidth = '0px'
+    }
+    if (_style.fontFamily) {
+      if (_style.fontFamily.length === 0) {
+        delete _style.fontFamily
+      } else {
+        _style.fontFamily = _style.fontFamily.join(',')
+      }
+    }
+    if (_style.lineHeight === 2.8) {
+      delete _style.lineHeight
     }
 
-    let _config = {...this.props.config, headerStyle: style}
+    let _config = {...this.props.config, headerStyle: _style}
     
     this.props.updateComponent(_config)
   }
@@ -48,9 +59,13 @@
   changeStyle = () => {
     const { config } = this.props
 
-    let options = ['font', 'border', 'background', 'padding']
+    let _style = config.headerStyle ? fromJS(config.headerStyle).toJS() : {}
+    let options = ['font', 'border', 'background', 'padding', 'fontFamily']
 
-    MKEmitter.emit('changeStyle', options, config.headerStyle, this.getStyle)
+    _style.fontFamily = _style.fontFamily ? _style.fontFamily.split(',') : []
+    _style.lineHeight = _style.lineHeight || 2.8
+
+    MKEmitter.emit('changeStyle', options, _style, this.getStyle)
   }
 
   render() {
diff --git a/src/menu/components/share/normalheader/index.scss b/src/menu/components/share/normalheader/index.scss
index 0d9f65f..cc3679c 100644
--- a/src/menu/components/share/normalheader/index.scss
+++ b/src/menu/components/share/normalheader/index.scss
@@ -12,6 +12,7 @@
     text-decoration: inherit;
     font-weight: inherit;
     font-style: inherit;
+    font-family: inherit;
     float: left;
     line-height: inherit;
     margin-left: 10px;
@@ -41,6 +42,10 @@
     border: 1px solid #d9d9d9;
     opacity: 0.6;
   }
+  .ant-input-search.ant-input-group-wrapper {
+    position: relative;
+    top: 5px;
+  }
 }
 .normal-header:not(.tree-search) {
   display: flex;
diff --git a/src/menu/components/share/searchcomponent/dragsearch/card.jsx b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
index 6061187..f13b469 100644
--- a/src/menu/components/share/searchcomponent/dragsearch/card.jsx
+++ b/src/menu/components/share/searchcomponent/dragsearch/card.jsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
-import { Select, DatePicker, Input, Popover, Form, Switch, Checkbox } from 'antd'
+import { Select, DatePicker, Input, Popover, Form, Switch, Checkbox, Radio } from 'antd'
 import { EditOutlined, CopyOutlined, CloseOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -105,15 +105,23 @@
       format={format}
       className="data-range"
       placeholder={['BeginTime', 'EndTime']}
-      renderExtraFooter={() => 'extra footer'}
+      renderExtraFooter={() => 'extra footer'} 
       value={_defaultValue}
     />
   } else if (card.type === 'group') {
     formItem = <DateGroup card={card} />
   } else if (card.type === 'switch') {
     formItem = (<Switch checkedChildren={card.openText || ''} unCheckedChildren={card.closeText || ''} style={{marginTop: '8px'}} checked={card.initval === card.openVal}/>)
+  } else if (card.type === 'radio') {
+    let options = card.options
+    if (options.length === 0) {
+      options = [{Value: '1', Text: '閫夐」1'}, {Value: '2', Text: '閫夐」2'}]
+    }
+    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '40px', whiteSpace: 'nowrap'}}>
+      {options.map((item, i) => (<Radio key={i} value={item.Value}> {item.Text} </Radio>))}
+    </Radio.Group>)
   } else if (card.type === 'check') {
-    formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
+    formItem = <Checkbox style={{lineHeight: '36px', whiteSpace: 'nowrap'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   } else if (card.type === 'range') {
     type = 'range-wrap'
     let vals = card.initval.split(',')
diff --git a/src/menu/components/share/searchcomponent/index.jsx b/src/menu/components/share/searchcomponent/index.jsx
index 6752638..b809cb9 100644
--- a/src/menu/components/share/searchcomponent/index.jsx
+++ b/src/menu/components/share/searchcomponent/index.jsx
@@ -93,6 +93,7 @@
    * @description 鎼滅储鏉′欢缂栬緫锛岃幏鍙栨悳绱㈡潯浠惰〃鍗曚俊鎭�
    */
   handleSearch = (card) => {
+    const { config } = this.props
     const { searchlist } = this.state
     let linkableFields = []
 
@@ -107,10 +108,17 @@
       })
     })
 
+    let columns = null
+    if (config.columns && config.columns.length) {
+      columns = config.columns.map(item => {
+        return {key: item.uuid, text: item.field, value: item.field, label: item.label}
+      })
+    }
+
     this.setState({
       visible: true,
       card: card,
-      formlist: getSearchForm(card, linkableFields, [], 'header')
+      formlist: getSearchForm(card, linkableFields, columns, 'header')
     })
   }
 
@@ -202,7 +210,8 @@
           sqlVerifing: true
         })
 
-        let sql = res.dataSource
+        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
 
         let rduri = ''
diff --git a/src/menu/components/share/searchcomponent/index.scss b/src/menu/components/share/searchcomponent/index.scss
index fd5bdac..48586a9 100644
--- a/src/menu/components/share/searchcomponent/index.scss
+++ b/src/menu/components/share/searchcomponent/index.scss
@@ -1,9 +1,14 @@
 .model-custom-header-search-list {
   padding: 0px;
 
-  .ant-row >.ant-col {
-    float: right;
-    padding: 0 6px;
+  >.ant-row {
+    text-align: right;
+    >.ant-col {
+      display: inline-block;
+      float: none;
+      padding: 0 6px;
+      text-align: left;
+    }
   }
 
   .page-card {
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 5636097..cd62ff5 100644
--- a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -103,6 +103,8 @@
       key: 'nameField',
       label: '鍚嶇О瀛楁',
       initVal: card.nameField || '',
+      tooltip: '鍚嶇О瀛楁涓洪摼鎺ュ湪鐣岄潰涓樉绀虹殑鍐呭锛屽湪閾炬帴涓互@***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: false,
       rules: [{
         max: 100,
@@ -118,20 +120,6 @@
       label: '鍒楀',
       initVal: card.Width || 120,
       required: true
-    },
-    {
-      type: 'radio',
-      key: 'joint',
-      label: '鎷兼帴鍙傛暟',
-      initVal: card.joint || 'true',
-      required: true,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
     },
     {
       type: 'radio',
@@ -440,15 +428,9 @@
       key: 'linkurl',
       label: '閾炬帴鍦板潃',
       initVal: card.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true
-    },
-    {
-      type: 'multiselect',
-      key: 'linkfields',
-      label: '鍏宠仈瀛楁',
-      initVal: card.linkfields || [],
-      required: false,
-      options: fields,
     },
     {
       type: 'textarea',
diff --git a/src/menu/components/table/base-table/columns/editColumn/index.jsx b/src/menu/components/table/base-table/columns/editColumn/index.jsx
index 8af9c30..dac43a3 100644
--- a/src/menu/components/table/base-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -11,7 +11,7 @@
 const columnTypeOptions = {
   text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'perspective', 'rowspan'],
   number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
-  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist', 'nameField'],
+  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'nameField'],
   textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'prefix', 'postfix', 'blacklist'],
   picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
   video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'fieldlength', 'blacklist', 'aspectRatio'],
@@ -91,9 +91,9 @@
 
     if (this.record.type === 'text' || this.record.type === 'number') {
       if (this.record.perspective === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
+        _options.push('linkmenu', 'open')
       } else if (this.record.perspective === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
+        _options.push('linkurl', 'open')
       }
     } else if (this.record.type === 'formula' && this.record.eval === 'true') {
       _options.push('decimal')
@@ -209,15 +209,19 @@
     formlist.forEach((item, index) => {
       if (item.hidden || item.forbid) return
 
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
+
       if (item.type === 'text') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -234,12 +238,7 @@
       } else if (item.type === 'number') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -256,7 +255,7 @@
       } else if (item.type === 'select') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -285,12 +284,7 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -312,12 +306,7 @@
       } else if (item.type === 'checkbox') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal
               })(
@@ -331,7 +320,7 @@
       } else if (item.type === 'multiselect') { // 澶氶��
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || []
               })(
@@ -351,7 +340,7 @@
       } else if (item.type === 'cascader') { // 澶氶��
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || [],
                 rules: [
@@ -374,12 +363,7 @@
         if (item.key === 'formula') {
           fields.push(
             <Col span={24} className="textarea" key={index}>
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+              <Form.Item label={label}>
                 {getFieldDecorator(item.key, {
                   initialValue: item.initVal || '',
                   rules: [
@@ -398,12 +382,7 @@
         } else {
           fields.push(
             <Col span={24} key={index} className="textarea">
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+              <Form.Item label={label}>
                 {getFieldDecorator(item.key, {
                   initialValue: item.initVal || '',
                   rules: [
diff --git a/src/menu/components/table/base-table/options.jsx b/src/menu/components/table/base-table/options.jsx
index 85ee2bf..288cd00 100644
--- a/src/menu/components/table/base-table/options.jsx
+++ b/src/menu/components/table/base-table/options.jsx
@@ -20,6 +20,17 @@
     },
     {
       type: 'radio',
+      field: 'parity',
+      label: '濂囧伓寮傝壊',
+      initval: wrap.parity || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'bordered',
       label: '杈规',
       initval: wrap.bordered || 'true',
@@ -36,8 +47,8 @@
       initval: wrap.actionfixed !== 'true' ? 'false' : 'true',
       required: false,
       options: [
-        {value: 'true', label: '鏄�'},
-        {value: 'false', label: '鍚�'},
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ]
     },
     {
@@ -64,20 +75,6 @@
         {value: 'small', label: '灏�'},
         {value: 'mini', label: '杩蜂綘'},
       ]
-    },
-    {
-      type: 'select',
-      field: 'selected',
-      label: '鏁版嵁閫変腑',
-      initval: wrap.selected || 'false',
-      tooltip: '鍒濆鍖栵細鏁版嵁鍔犺浇鏃堕�変腑棣栬鏁版嵁锛屼粎鎵ц涓�娆°�傛暟鎹姞杞斤細姣忔鏁版嵁鍔犺浇鏃跺潎閫変腑棣栬锛堝綋鎸夐挳鎵ц瀹屾垚骞惰繑鍥炰富閿�兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇锛夈�傞�変腑鏍囪锛氳繑鍥炴暟鎹腑瀛樺湪 selected 瀛楁锛屼笖鍊间负 true 鐨勬暟鎹閫変腑銆傛敞锛氬惎鐢ㄦ棤浜哄�煎畧鏃舵棤鏁堛��',
-      required: false,
-      options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'init', label: '鍒濆鍖�'},
-        {value: 'always', label: '鏁版嵁鍔犺浇'},
-        {value: 'sign', label: '閫変腑鏍囪'}
-      ],
     },
     // {
     //   type: 'radio',
@@ -138,15 +135,18 @@
       ]
     },
     {
-      type: 'number',
-      field: 'btnlimit',
-      label: '鎸夐挳闄愬埗',
-      initval: wrap.btnlimit || '',
-      tooltip: '鎸夐挳鏁伴噺闄愬埗锛岃秴鍑虹殑鎸夐挳浼氬湪鏇村涓笅鎷夋樉绀猴紝娉細鏇村涓殑鎸夐挳涓嶈缁戝畾鍙屽嚮浜嬩欢銆�',
-      min: 3,
-      max: 3000,
-      precision: 0,
-      required: false
+      type: 'select',
+      field: 'selected',
+      label: '鏁版嵁閫変腑',
+      initval: wrap.selected || 'false',
+      tooltip: '鍒濆鍖栵細鏁版嵁鍔犺浇鏃堕�変腑棣栬鏁版嵁锛屼粎鎵ц涓�娆°�傛暟鎹姞杞斤細姣忔鏁版嵁鍔犺浇鏃跺潎閫変腑棣栬锛堝綋鎸夐挳鎵ц瀹屾垚骞惰繑鍥炰富閿�兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇锛夈�傞�変腑鏍囪锛氳繑鍥炴暟鎹腑瀛樺湪 selected 瀛楁锛屼笖鍊间负 true 鐨勬暟鎹閫変腑銆傛敞锛氬惎鐢ㄦ棤浜哄�煎畧鏃舵棤鏁堛��',
+      required: false,
+      options: [
+        {value: 'false', label: '鏃�'},
+        {value: 'init', label: '鍒濆鍖�'},
+        {value: 'always', label: '鏁版嵁鍔犺浇'},
+        {value: 'sign', label: '閫変腑鏍囪'}
+      ],
     },
     {
       type: 'number',
@@ -211,6 +211,17 @@
     },
     {
       type: 'number',
+      field: 'btnlimit',
+      label: '鎸夐挳闄愬埗',
+      initval: wrap.btnlimit || '',
+      tooltip: '鎸夐挳鏁伴噺闄愬埗锛岃秴鍑虹殑鎸夐挳浼氬湪鏇村涓笅鎷夋樉绀猴紝娉細鏇村涓殑鎸夐挳涓嶈缁戝畾鍙屽嚮浜嬩欢銆�',
+      min: 3,
+      max: 3000,
+      precision: 0,
+      required: false
+    },
+    {
+      type: 'number',
       field: 'maxPageSize',
       label: '姣忛〉鏈�澶ф暟',
       initval: wrap.maxPageSize || '',
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 c34c943..4379c5c 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -37,6 +37,9 @@
     value: 'colspan',
     text: '鍚堝苟鍒�'
   }, {
+    value: 'extend',
+    text: '鎵╁睍鍒�'
+  }, {
     value: 'index',
     text: '搴忓彿'
   }]
@@ -210,6 +213,95 @@
     },
     {
       type: 'radio',
+      key: 'colUnit',
+      label: '鍗曚綅',
+      initVal: card.colUnit || 'day',
+      required: true,
+      options: [{
+        value: 'day',
+        text: '澶�'
+      }, {
+        value: 'hour',
+        text: '灏忔椂'
+      }]
+    },
+    {
+      type: 'number',
+      key: 'shift',
+      label: '鍋忕Щ閲�',
+      initVal: card.shift || 0,
+      min: -1000,
+      max: 1000,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'quota',
+      label: '鎸囨爣鏁�',
+      initVal: card.quota || 7,
+      min: 1,
+      max: 1000,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'dayFormat',
+      label: '鏍煎紡鍖�',
+      initVal: card.dayFormat || 'M/DD',
+      required: true,
+      options: [{
+        value: 'M/DD',
+        label: 'M/DD锛�4/29锛�'
+      }, {
+        value: 'M-DD',
+        label: 'M-DD锛�4-29锛�'
+      }, {
+        value: 'M鏈圖D鏃�',
+        label: 'M鏈圖D鏃ワ紙4鏈�29鏃ワ級'
+      }, {
+        value: 'M/DD week',
+        label: 'M/DD week锛�4/29 鏄熸湡涓�锛�'
+      }, {
+        value: 'M-DD week',
+        label: 'M-DD week锛�4-29 鏄熸湡涓�锛�'
+      }, {
+        value: 'M鏈圖D鏃� week',
+        label: 'M鏈圖D鏃� week锛�4鏈�29鏃� 鏄熸湡涓�锛�'
+      }]
+    },
+    {
+      type: 'select',
+      key: 'hourFormat',
+      label: '鏍煎紡鍖�',
+      initVal: card.hourFormat || 'H:00',
+      required: true,
+      options: [{
+        value: 'H:00',
+        label: 'H:00锛�15:00锛�'
+      }, {
+        value: 'H point',
+        label: 'H锛�15鐐癸級'
+      }, {
+        value: 'h:00',
+        label: 'h:00锛�3:00 pm锛�'
+      }]
+    },
+    {
+      type: 'text',
+      key: 'supField',
+      label: '涓婄骇瀛楁',
+      initVal: card.supField || '',
+      tooltip: '鏉ユ簮浜庝笂绾х粍浠剁殑瀛楁闆嗭紙涓婄骇缁勪欢涓虹┖鏃朵粠url鍙傛暟涓�夊彇锛夛紝璇ュ瓧娈靛�硷紙鐢ㄩ�楀彿鍒嗛殧锛夊彲鎺у埗鎵╁睍鍒楃殑鍒楀悕銆�',
+      required: false,
+      rules: [{
+        pattern: /^[0-9a-zA-Z_]*$/ig,
+        message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶄互鍙奯'
+      }]
+    },
+    {
+      type: 'radio',
       key: 'editable',
       label: '鍙紪杈�',
       initVal: card.editable || 'false',
@@ -276,6 +368,20 @@
       }, {
         value: 'nvarchar(50)',
         text: 'nvarchar(50)'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'required',
+      label: '蹇呭~',
+      initVal: card.required || 'false',
+      required: false,
+      options: [{
+        value: 'false',
+        text: '鍚�'
+      }, {
+        value: 'true',
+        text: '鏄�'
       }]
     },
     {
@@ -576,20 +682,6 @@
       }, {
         value: 'fixed',
         text: '瀹氬'
-      }]
-    },
-    {
-      type: 'radio',
-      key: 'required',
-      label: '蹇呭~',
-      initVal: card.required || 'false',
-      required: false,
-      options: [{
-        value: 'false',
-        text: '鍚�'
-      }, {
-        value: 'true',
-        text: '鏄�'
       }]
     },
     {
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 fd16488..dd97ea0 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -23,6 +23,7 @@
   textarea: ['label', 'field', 'type', 'Align', 'Hide', 'Width', 'prefix', 'initval', 'postfix', 'blacklist'],
   custom: ['label', 'type', 'Align', 'Width', 'blacklist', 'IsSort'],
   colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
+  extend: ['label', 'field', 'type', 'Align', 'Width', 'colUnit', 'shift', 'quota', 'supField'],
   action: ['label', 'type', 'Align', 'Width'],
   formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
   index: ['label', 'type', 'Align', 'Width']
@@ -65,6 +66,8 @@
   getOptions = () => {
     let _options = fromJS(columnTypeOptions[this.record.type]).toJS()
 
+    let reLabel = {}
+
     if (['number', 'text'].includes(this.record.type) && this.record.editable === 'true') {
       _options.push('ctrlField')
       if (this.record.ctrlField) {
@@ -90,8 +93,18 @@
         } else {
           _options.push('required', 'enter')
         }
+
+        reLabel.required = '蹇呭~'
       } else if (this.record.type === 'number') {
-        _options.push('max', 'min', 'enter', 'clearField')
+        _options.push('max', 'min', 'required', 'enter', 'clearField')
+
+        reLabel.required = '涓嶇瓑浜�0'
+      }
+    } else if (this.record.type === 'extend') {
+      if (this.record.colUnit === 'day') {
+        _options.push('dayFormat')
+      } else {
+        _options.push('hourFormat')
       }
     }
     if (this.record.type === 'formula' && this.record.eval === 'true') {
@@ -108,7 +121,7 @@
       }
     }
 
-    return _options
+    return {options: _options, reLabel}
   }
 
   editColumn = (column) => {
@@ -124,12 +137,16 @@
       this.record[item.key] = item.initVal
     })
     
-    let _options = this.getOptions()
+    let { options, reLabel } = this.getOptions()
 
     this.setState({
       visible: true,
       formlist: formlist.map(item => {
-        item.hidden = !_options.includes(item.key)
+        item.hidden = !options.includes(item.key)
+
+        if (reLabel[item.key]) {
+          item.label = reLabel[item.key]
+        }
 
         if (item.key === 'formula') {
           item.fields = this.props.fields.map(col => col.field)
@@ -159,7 +176,7 @@
         this.record.IsSort = 'false'
       }
 
-      let _options = this.getOptions()
+      let { options, reLabel } = this.getOptions()
 
       let _field = ''
       if (value === 'formula') {
@@ -173,7 +190,10 @@
           }
 
           item.initVal = this.record[item.key]
-          item.hidden = !_options.includes(item.key)
+          item.hidden = !options.includes(item.key)
+          if (reLabel[item.key]) {
+            item.label = reLabel[item.key]
+          }
 
           return item
         })
@@ -205,12 +225,15 @@
       this.record.type = values.type
 
       if (values.type !== _type) {
-        let _options = this.getOptions()
+        let { options, reLabel } = this.getOptions()
 
         this.setState({
           formlist: this.state.formlist.map(item => {
             item.initVal = this.record[item.key]
-            item.hidden = !_options.includes(item.key)
+            item.hidden = !options.includes(item.key)
+            if (reLabel[item.key]) {
+              item.label = reLabel[item.key]
+            }
 
             return item
           })
@@ -223,7 +246,7 @@
     } else if (key === 'format' && value === 'percent') {
       this.props.form.setFieldsValue({postfix: '%'})
     } else if (key === 'editType') {
-      let _options = this.getOptions()
+      let { options, reLabel } = this.getOptions()
 
       this.setState({
         formlist: this.state.formlist.map(item => {
@@ -232,18 +255,24 @@
           }
 
           item.initVal = this.record[item.key]
-          item.hidden = !_options.includes(item.key)
+          item.hidden = !options.includes(item.key)
+          if (reLabel[item.key]) {
+            item.label = reLabel[item.key]
+          }
 
           return item
         })
       })
     } else if (['editable', 'editType', 'resourceType', 'ctrlField', 'eval', 'Hide', 'IsSort', 'textFormat'].includes(key)) {
-      let _options = this.getOptions()
+      let { options, reLabel } = this.getOptions()
 
       this.setState({
         formlist: this.state.formlist.map(item => {
           item.initVal = this.record[item.key]
-          item.hidden = !_options.includes(item.key)
+          item.hidden = !options.includes(item.key)
+          if (reLabel[item.key]) {
+            item.label = reLabel[item.key]
+          }
 
           return item
         })
@@ -311,6 +340,14 @@
       let content = null
       let extra = null
       let initVal = item.initVal || ''
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
 
       if (item.type === 'text') {
         rules = [
@@ -385,12 +422,7 @@
         if (item.key === 'formula') {
           fields.push(
             <Col span={span} key={index}>
-              <Form.Item className={className} extra={extra} label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+              <Form.Item className={className} extra={extra} label={label}>
                 {getFieldDecorator(item.key, {
                   initialValue: initVal,
                   rules: rules
@@ -447,12 +479,7 @@
 
       fields.push(
         <Col span={span} key={index}>
-          <Form.Item className={className} extra={extra} label={item.tooltip ?
-            <Tooltip placement="topLeft" title={item.tooltip}>
-              <QuestionCircleOutlined className="mk-form-tip" />
-              {item.label}
-            </Tooltip> : item.label
-          }>
+          <Form.Item className={className} extra={extra} label={label}>
             {getFieldDecorator(item.key, {
               initialValue: initVal,
               rules: rules
diff --git a/src/menu/components/table/edit-table/columns/index.jsx b/src/menu/components/table/edit-table/columns/index.jsx
index 0956ffd..b410cc8 100644
--- a/src/menu/components/table/edit-table/columns/index.jsx
+++ b/src/menu/components/table/edit-table/columns/index.jsx
@@ -109,7 +109,7 @@
             {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
             {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
             <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+            {['text', 'number', 'formula', 'extend'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
           </div>
         } trigger="hover">
           {children}
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 0e64f59..e1a539a 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
@@ -36,7 +36,7 @@
     fields.push('jskey')
 
     let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
-    let _sql = `create table #${sheet} (${usefulfields.map(item => item.field + ' ' + item.datatype).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50))
+    let _sql = `create table #${sheet} (${usefulfields.map(item => item.field + ' ' + item.datatype).join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
       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=''
     `
@@ -266,7 +266,7 @@
           </Col> : null}
           {!type ? <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
diff --git a/src/menu/components/table/edit-table/columns/tableIn/index.jsx b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
index ddfa334..0b443d7 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -566,7 +566,8 @@
                       <Select.Option value="line" disabled={config.wrap.commit !== 'change'}>鍒锋柊琛�</Select.Option>
                       <Select.Option value="grid">鍒锋柊缁勪欢</Select.Option>
                       <Select.Option value="line_grid" disabled={config.wrap.commit !== 'change'}>鍒锋柊琛� / 缁勪欢</Select.Option>
-                      <Select.Option value="mainline">涓婄骇锛堣锛�</Select.Option>
+                      <Select.Option value="mainline">鍒锋柊涓婄骇缁勪欢 - 琛�</Select.Option>
+                      <Select.Option value="maingrid">鍒锋柊涓婄骇缁勪欢</Select.Option>
                     </Select>
                   </Form.Item>
                 </Col>
@@ -577,7 +578,8 @@
                       <Select.Option value="line" disabled={config.wrap.commit !== 'change'}>鍒锋柊琛�</Select.Option>
                       <Select.Option value="grid">鍒锋柊缁勪欢</Select.Option>
                       <Select.Option value="line_grid" disabled={config.wrap.commit !== 'change'}>鍒锋柊琛� / 缁勪欢</Select.Option>
-                      <Select.Option value="mainline">涓婄骇锛堣锛�</Select.Option>
+                      <Select.Option value="mainline">鍒锋柊涓婄骇缁勪欢 - 琛�</Select.Option>
+                      <Select.Option value="maingrid">鍒锋柊涓婄骇缁勪欢</Select.Option>
                     </Select>
                   </Form.Item>
                 </Col>
diff --git a/src/menu/components/table/edit-table/columns/tableIn/index.scss b/src/menu/components/table/edit-table/columns/tableIn/index.scss
index 16b42cb..2f0266d 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.scss
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.scss
@@ -52,10 +52,6 @@
   .custom-table .ant-empty {
     margin: 20px 8px!important;
   }
-  .excel-custom-table {
-    position: relative;
-    top: -25px;
-  }
   .errorval {
     display: inline-block;
     width: 30px;
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index e005989..b6bfbee 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -296,6 +296,25 @@
   updatecolumn = (config) => {
     config.absFields = []
     config.mergeCol = false
+    config.hasExtend = false
+    config.parCtrl = false
+
+    let mapCol = (cols) => {
+      cols.forEach(col => {
+        if (col.type === 'number') {
+          if (col.format === 'abs') {
+            config.absFields.push(col.field)
+          }
+        } else if (col.type === 'extend') {
+          config.hasExtend = true
+          if (col.supField) {
+            config.parCtrl = true
+          }
+        } else if (col.type === 'colspan' && col.subcols) {
+          mapCol(col.subcols)
+        }
+      })
+    }
 
     config.cols.forEach((col, index) => {
       delete col.pops
@@ -304,14 +323,13 @@
         if (col.format === 'abs') {
           config.absFields.push(col.field)
         }
+      } else if (col.type === 'extend') {
+        config.hasExtend = true
+        if (col.supField) {
+          config.parCtrl = true
+        }
       } else if (col.type === 'colspan' && col.subcols) {
-        col.subcols.forEach(scol => {
-          if (scol.type === 'number') {
-            if (scol.format === 'abs') {
-              config.absFields.push(scol.field)
-            }
-          }
-        })
+        mapCol(col.subcols)
       } else if (col.type === 'text') {
         if (col.editable === 'true' && col.editType === 'popSelect' && /^tab:/.test(col.initval)) {
           config.mergeCol = config.mergeCol || []
diff --git a/src/menu/components/table/edit-table/options.jsx b/src/menu/components/table/edit-table/options.jsx
index 7773bdf..f3e8d31 100644
--- a/src/menu/components/table/edit-table/options.jsx
+++ b/src/menu/components/table/edit-table/options.jsx
@@ -129,7 +129,18 @@
         {value: 'default', label: '澶�'},
         {value: 'middle', label: '涓�'},
         {value: 'small', label: '灏�'},
-        {value: 'mini', label: '杩蜂綘'},
+        // {value: 'mini', label: '杩蜂綘'},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'parity',
+      label: '濂囧伓寮傝壊',
+      initval: wrap.parity || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ]
     },
     {
@@ -193,7 +204,7 @@
       initval: wrap.permission || (!appType ? 'true' : 'false'),
       required: false,
       options: [
-        {value: 'true', label: '鍚敤'},
+        {value: 'true', label: !appType ? '缁ф壙鑿滃崟' : '鍚敤'},
         {value: 'false', label: '绂佺敤'},
       ],
       forbid: sessionStorage.getItem('editMenuType') === 'popview'
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 b50848d..6ad02d3 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -61,10 +61,17 @@
     value: 'colspan',
     text: '鍚堝苟鍒�'
   }, {
+    value: 'extend',
+    text: '鎵╁睍鍒�'
+  }, {
     value: 'index',
     text: '搴忓彿'
   }]
 
+  if (appType === 'mob') {
+    options = options.filter(item => item.value !== 'extend')
+  }
+  
   if (!card.linkurl && (!card.linkmenu || card.linkmenu.length === 0)) {
     card.perspective = ''
   }
@@ -98,6 +105,8 @@
       key: 'nameField',
       label: '鍚嶇О瀛楁',
       initVal: card.nameField || '',
+      tooltip: '鍚嶇О瀛楁涓洪摼鎺ュ湪鐣岄潰涓樉绀虹殑鍐呭锛屽湪閾炬帴涓互@***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: false,
       options: [{uuid: 'empty', field: '', label: '绌�'}, ...fields]
     },
@@ -110,20 +119,6 @@
       label: '鍒楀',
       initVal: card.Width || 120,
       required: true
-    },
-    {
-      type: 'radio',
-      key: 'joint',
-      label: '鎷兼帴鍙傛暟',
-      initVal: card.joint || 'true',
-      required: true,
-      options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
-        value: 'false',
-        text: '鍚�'
-      }]
     },
     {
       type: 'radio',
@@ -194,6 +189,95 @@
       }, {
         value: 'right',
         text: '鍙冲榻�'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'colUnit',
+      label: '鍗曚綅',
+      initVal: card.colUnit || 'day',
+      required: true,
+      options: [{
+        value: 'day',
+        text: '澶�'
+      }, {
+        value: 'hour',
+        text: '灏忔椂'
+      }]
+    },
+    {
+      type: 'number',
+      key: 'shift',
+      label: '鍋忕Щ閲�',
+      initVal: card.shift || 0,
+      min: -1000,
+      max: 1000,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'number',
+      key: 'quota',
+      label: '鎸囨爣鏁�',
+      initVal: card.quota || 7,
+      min: 1,
+      max: 1000,
+      decimal: 0,
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'dayFormat',
+      label: '鏍煎紡鍖�',
+      initVal: card.dayFormat || 'M/DD',
+      required: true,
+      options: [{
+        value: 'M/DD',
+        label: 'M/DD锛�4/29锛�'
+      }, {
+        value: 'M-DD',
+        label: 'M-DD锛�4-29锛�'
+      }, {
+        value: 'M鏈圖D鏃�',
+        label: 'M鏈圖D鏃ワ紙4鏈�29鏃ワ級'
+      }, {
+        value: 'M/DD week',
+        label: 'M/DD week锛�4/29 鏄熸湡涓�锛�'
+      }, {
+        value: 'M-DD week',
+        label: 'M-DD week锛�4-29 鏄熸湡涓�锛�'
+      }, {
+        value: 'M鏈圖D鏃� week',
+        label: 'M鏈圖D鏃� week锛�4鏈�29鏃� 鏄熸湡涓�锛�'
+      }]
+    },
+    {
+      type: 'select',
+      key: 'hourFormat',
+      label: '鏍煎紡鍖�',
+      initVal: card.hourFormat || 'H:00',
+      required: true,
+      options: [{
+        value: 'H:00',
+        label: 'H:00锛�15:00锛�'
+      }, {
+        value: 'H point',
+        label: 'H锛�15鐐癸級'
+      }, {
+        value: 'h:00',
+        label: 'h:00锛�3:00 pm锛�'
+      }]
+    },
+    {
+      type: 'text',
+      key: 'supField',
+      label: '涓婄骇瀛楁',
+      initVal: card.supField || '',
+      tooltip: '鏉ユ簮浜庝笂绾х粍浠剁殑瀛楁闆嗭紙涓婄骇缁勪欢涓虹┖鏃朵粠url鍙傛暟涓�夊彇锛夛紝璇ュ瓧娈靛�硷紙鐢ㄩ�楀彿鍒嗛殧锛夊彲鎺у埗鎵╁睍鍒楃殑鍒楀悕銆�',
+      required: false,
+      rules: [{
+        pattern: /^[0-9a-zA-Z_]*$/ig,
+        message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶄互鍙奯'
       }]
     },
     {
@@ -402,16 +486,9 @@
       key: 'linkurl',
       label: '閾炬帴鍦板潃',
       initVal: card.linkurl || '',
+      tooltip: '鍦ㄩ摼鎺ヤ腑浠***@褰㈠紡鎷兼帴鐨勫瓧娈碉紙瀛楁鏉ユ簮浜庡瓧娈甸泦涓紝姝ゅ id銆乤ppkey銆乽serid銆丩oginUID 涓虹郴缁熷瓧娈碉級锛岃烦杞椂灏嗘浛鎹负瀵瑰簲鍊硷紝渚嬪锛歨ttp://sso.mk9h.cn/doc/index.html?appkey=@appkey@&LoginUID=@LoginUID@锛屽叾涓璦ppkey涓嶭oginUID灏嗚鏇挎崲銆�',
+      toolWidth: 350,
       required: true,
-      forbid: appType === 'mob'
-    },
-    {
-      type: 'multiselect',
-      key: 'linkfields',
-      label: '鍏宠仈瀛楁',
-      initVal: card.linkfields || [],
-      required: false,
-      options: fields,
       forbid: appType === 'mob'
     },
     {
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 bb4f805..5f3d09c 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/index.jsx
@@ -12,7 +12,7 @@
 const columnTypeOptions = {
   text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'blacklist', 'perspective', 'rowspan'],
   number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
-  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist', 'nameField'],
+  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'nameField'],
   textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'blacklist'],
   picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'backgroundSize', 'span', 'lostTip'],
   video: ['label', 'field', 'type', 'Align', 'Hide', 'startTime', 'Width', 'blacklist', 'aspectRatio'],
@@ -20,6 +20,7 @@
   custom: ['label', 'type', 'Align', 'Width', 'blacklist', 'IsSort'],
   action: ['label', 'type', 'Align', 'Width'],
   formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
+  extend: ['label', 'field', 'type', 'Align', 'Width', 'colUnit', 'shift', 'quota', 'supField'],
   index: ['label', 'type', 'Align', 'Width']
 }
 
@@ -89,14 +90,20 @@
 
     if (this.record.type === 'text' || this.record.type === 'number') {
       if (this.record.perspective === 'linkmenu') {
-        _options.push('linkmenu', 'linkfields', 'open')
+        _options.push('linkmenu', 'open')
       } else if (this.record.perspective === 'linkurl') {
-        _options.push('linkurl', 'linkfields', 'open')
+        _options.push('linkurl', 'open')
       }
     } else if (this.record.type === 'formula' && this.record.eval === 'true') {
       _options.push('decimal')
     } else if (this.record.type === 'custom' && this.record.IsSort === 'true') {
       _options.push('sortField')
+    } else if (this.record.type === 'extend') {
+      if (this.record.colUnit === 'day') {
+        _options.push('dayFormat')
+      } else {
+        _options.push('hourFormat')
+      }
     }
 
     if (this.record.Hide !== 'true') {
@@ -186,7 +193,7 @@
       }
     } else if (key === 'format' && value === 'percent') {
       this.props.form.setFieldsValue({postfix: '%'})
-    } else if (['perspective', 'eval', 'IsSort', 'textFormat'].includes(key)) {
+    } else if (['perspective', 'eval', 'IsSort', 'textFormat', 'colUnit'].includes(key)) {
       let _options = this.getOptions()
 
       this.setState({
@@ -210,22 +217,26 @@
     formlist.forEach((item, index) => {
       if (item.hidden || item.forbid) return
 
+      let label = item.label
+      if (item.tooltip) {
+        if (item.toolWidth) {
+          label = <Tooltip placement="topLeft" overlayStyle={{maxWidth: item.toolWidth}} title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        } else {
+          label = <Tooltip placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>{item.tooltip}</div>}><QuestionCircleOutlined className="mk-form-tip" />{item.label}</Tooltip>
+        }
+      }
+
       if (item.type === 'text') {
-        let rules = []
+        let rules = item.rules || []
         if (item.key !== 'linkurl') {
-          rules = [{
+          rules.push({
             max: formRule.input.max,
             message: formRule.input.message
-          }]
+          })
         }
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -242,12 +253,7 @@
       } else if (item.type === 'number') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -264,7 +270,7 @@
       } else if (item.type === 'select') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || '',
                 rules: [
@@ -293,12 +299,7 @@
       } else if (item.type === 'radio') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal,
                 rules: [
@@ -320,12 +321,7 @@
       } else if (item.type === 'checkbox') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" title={item.tooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal
               })(
@@ -339,7 +335,7 @@
       } else if (item.type === 'multiselect') { // 澶氶��
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || []
               })(
@@ -356,10 +352,10 @@
             </Form.Item>
           </Col>
         )
-      } else if (item.type === 'cascader') { // 澶氶��
+      } else if (item.type === 'cascader') {
         fields.push(
           <Col span={12} key={index}>
-            <Form.Item label={item.label}>
+            <Form.Item label={label}>
               {getFieldDecorator(item.key, {
                 initialValue: item.initVal || [],
                 rules: [
@@ -382,12 +378,7 @@
         if (item.key === 'formula') {
           fields.push(
             <Col span={24} className="textarea" key={index}>
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+              <Form.Item label={label}>
                 {getFieldDecorator(item.key, {
                   initialValue: item.initVal || '',
                   rules: [
@@ -406,12 +397,7 @@
         } else {
           fields.push(
             <Col span={24} key={index} className="textarea">
-              <Form.Item label={item.tooltip ?
-                <Tooltip placement="topLeft" title={item.tooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  {item.label}
-                </Tooltip> : item.label
-              }>
+              <Form.Item label={label}>
                 {getFieldDecorator(item.key, {
                   initialValue: item.initVal || '',
                   rules: [
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index a7a32e9..0279ed8 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -109,7 +109,7 @@
             {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
             {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
             <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
-            {['text', 'number', 'formula'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+            {['text', 'number', 'formula', 'extend'].includes(column.type) ? <MarkColumn field={column.field || ''} columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
           </div>
         } trigger="hover">
           {children}
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index 6bdefb2..d53420d 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -278,11 +278,11 @@
   }
 
   getWrapForms = () => {
-    const { wrap, action, columns, cols } = this.state.card
+    const { card } = this.state
 
     let _actions = []
 
-    cols.forEach(col => {
+    card.cols.forEach(col => {
       if (col.type === 'custom') {
         col.elements.forEach(cell => {
           if (cell.eleType !== 'button') return
@@ -292,7 +292,7 @@
       }
     })
 
-    return getWrapForm(wrap, _actions, columns, action)
+    return getWrapForm(card.wrap, _actions, card.columns, card.action, card.supNodes || [], card.uuid)
   }
 
   updateWrap = (res) => {
@@ -311,26 +311,44 @@
     res.borderRadius = card.wrap.borderRadius || 0
     res.resetContrl = card.wrap.resetContrl || 'init'
 
-    this.updateComponent({...card, wrap: res})
+    let _card = {...card, wrap: res}
+
+    if (res.supNodes) {
+      _card.supNodes = res.supNodes
+      _card.supNodes = _card.supNodes.map(item => {
+        item.componentId = item.nodes[item.nodes.length - 1]
+        return item
+      })
+
+      delete res.supNodes
+    } else {
+      delete _card.supNodes
+    }
+
+    this.updateComponent(_card)
   }
 
   updatecolumn = (config) => {
     config.absFields = []
-    config.cols.forEach(col => {
-      if (col.type === 'number') {
-        if (col.format === 'abs') {
-          config.absFields.push(col.field)
-        }
-      } else if (col.type === 'colspan' && col.subcols) {
-        col.subcols.forEach(scol => {
-          if (scol.type === 'number') {
-            if (scol.format === 'abs') {
-              config.absFields.push(scol.field)
-            }
+    config.hasExtend = false
+    config.parCtrl = false
+    let mapCol = (cols) => {
+      cols.forEach(col => {
+        if (col.type === 'number') {
+          if (col.format === 'abs') {
+            config.absFields.push(col.field)
           }
-        })
-      }
-    })
+        } else if (col.type === 'extend') {
+          config.hasExtend = true
+          if (col.supField) {
+            config.parCtrl = true
+          }
+        } else if (col.type === 'colspan' && col.subcols) {
+          mapCol(col.subcols)
+        }
+      })
+    }
+    mapCol(config.cols)
 
     if (config.absFields.length) {
       config.absFields = Array.from(new Set(config.absFields))
@@ -389,7 +407,7 @@
         </Popover>
         {appType !== 'mob' ? <SearchComponent config={card} updatesearch={this.updateComponent}/> : null}
         <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
-        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
+        <ColumnComponent config={card} updatecolumn={this.updatecolumn}/>
         <div className="component-name">
           <div className="center">
             <div className="title" onDoubleClick={() => {
diff --git a/src/menu/components/table/normal-table/options.jsx b/src/menu/components/table/normal-table/options.jsx
index 416258c..22662e1 100644
--- a/src/menu/components/table/normal-table/options.jsx
+++ b/src/menu/components/table/normal-table/options.jsx
@@ -1,7 +1,9 @@
+import MenuUtils from '@/utils/utils-custom.js'
+
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
-export default function (wrap, action = [], columns = [], toolBtns) {
+export default function (wrap, action = [], columns = [], toolBtns, supNodes, id = '') {
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
   let isprint = sessionStorage.getItem('MenuType') === 'billPrint'
@@ -16,6 +18,9 @@
   } else {
     roleList = []
   }
+
+  let menu = window.GLOB.customMenu
+  let modules = MenuUtils.getSupModules(menu.components, id, menu.interfaces)
 
   const wrapForm = [
     {
@@ -69,6 +74,17 @@
       ],
       controlFields: [
         {field: 'selected', values: ['radio', 'checkbox']},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'parity',
+      label: '濂囧伓寮傝壊',
+      initval: wrap.parity || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
       ]
     },
     {
@@ -155,20 +171,6 @@
       ]
     },
     {
-      type: 'select',
-      field: 'selected',
-      label: '鏁版嵁閫変腑',
-      initval: wrap.selected || 'false',
-      tooltip: '鍒濆鍖栵細鏁版嵁鍔犺浇鏃堕�変腑棣栬鏁版嵁锛屼粎鎵ц涓�娆°�傛暟鎹姞杞斤細姣忔鏁版嵁鍔犺浇鏃跺潎閫変腑棣栬锛堝綋鎸夐挳鎵ц瀹屾垚骞惰繑鍥炰富閿�兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇锛夈�傞�変腑鏍囪锛氳繑鍥炴暟鎹腑瀛樺湪 selected 瀛楁锛屼笖鍊间负 true 鐨勬暟鎹閫変腑銆�',
-      required: false,
-      options: [
-        {value: 'false', label: '鏃�'},
-        {value: 'init', label: '鍒濆鍖�'},
-        {value: 'always', label: '鏁版嵁鍔犺浇'},
-        {value: 'sign', label: '閫変腑鏍囪'}
-      ],
-    },
-    {
       type: 'color',
       field: 'borderColor',
       label: '杈规棰滆壊',
@@ -190,16 +192,18 @@
       ]
     },
     {
-      type: 'number',
-      field: 'btnlimit',
-      label: '鎸夐挳闄愬埗',
-      initval: wrap.btnlimit || '',
-      tooltip: '鎸夐挳鏁伴噺闄愬埗锛岃秴鍑虹殑鎸夐挳浼氬湪鏇村涓笅鎷夋樉绀猴紝娉細鏇村涓殑鎸夐挳涓嶈缁戝畾鍙屽嚮浜嬩欢銆�',
-      min: 3,
-      max: 3000,
-      precision: 0,
+      type: 'select',
+      field: 'selected',
+      label: '鏁版嵁閫変腑',
+      initval: wrap.selected || 'false',
+      tooltip: '鍒濆鍖栵細鏁版嵁鍔犺浇鏃堕�変腑棣栬鏁版嵁锛屼粎鎵ц涓�娆°�傛暟鎹姞杞斤細姣忔鏁版嵁鍔犺浇鏃跺潎閫変腑棣栬锛堝綋鎸夐挳鎵ц瀹屾垚骞惰繑鍥炰富閿�兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇锛夈�傞�変腑鏍囪锛氳繑鍥炴暟鎹腑瀛樺湪 selected 瀛楁锛屼笖鍊间负 true 鐨勬暟鎹閫変腑銆�',
       required: false,
-      forbid: appType !== '' || isprint
+      options: [
+        {value: 'false', label: '鏃�'},
+        {value: 'init', label: '鍒濆鍖�'},
+        {value: 'always', label: '鏁版嵁鍔犺浇'},
+        {value: 'sign', label: '閫変腑鏍囪'}
+      ],
     },
     {
       type: 'select',
@@ -254,6 +258,18 @@
     },
     {
       type: 'number',
+      field: 'btnlimit',
+      label: '鎸夐挳闄愬埗',
+      initval: wrap.btnlimit || '',
+      tooltip: '鎸夐挳鏁伴噺闄愬埗锛岃秴鍑虹殑鎸夐挳浼氬湪鏇村涓笅鎷夋樉绀猴紝娉細鏇村涓殑鎸夐挳涓嶈缁戝畾鍙屽嚮浜嬩欢銆�',
+      min: 3,
+      max: 3000,
+      precision: 0,
+      required: false,
+      forbid: appType !== '' || isprint
+    },
+    {
+      type: 'number',
       field: 'maxPageSize',
       label: '姣忛〉鏈�澶ф暟',
       initval: wrap.maxPageSize || '',
@@ -288,6 +304,22 @@
         {value: 'false', label: '蹇界暐'},
       ],
       forbid: isprint
+    },
+    {
+      type: 'radio',
+      field: 'supType',
+      label: '涓婄骇绫诲瀷',
+      initval: wrap.supType || 'single',
+      tooltip: '涓婄骇缁勪欢涓哄崟涓�缁勪欢鎴栧涓粍浠躲��',
+      required: false,
+      forbid: appType === 'mob' || isprint,
+      options: [
+        {value: 'single', label: '鍗曠粍浠�'},
+        {value: 'multi', label: '澶氱粍浠�'},
+      ],
+      controlFields: [
+        {field: 'supNodes', values: ['multi']},
+      ]
     },
     {
       type: 'radio',
@@ -335,6 +367,36 @@
       options: roleList,
       forbid: !!appType || isprint
     },
+    {
+      type: 'table',
+      field: 'supNodes',
+      label: '涓婄骇缁勪欢',
+      initval: supNodes,
+      required: true,
+      forbid: appType === 'mob' || isprint,
+      span: 24,
+      actions: ['edit', 'del', 'add', 'move'],
+      columns: [
+        {
+          title: '搴忓彿',
+          dataIndex: '$index',
+          editable: false,
+          required: false,
+          width: '20%'
+        },
+        {
+          title: '缁勪欢',
+          dataIndex: 'nodes',
+          inputType: 'cascader',
+          editable: true,
+          required: true,
+          extends: [{key: 'label', value: 'label'}],
+          width: '50%',
+          render: (text, record) => record.label,
+          options: modules
+        }
+      ]
+    }
   ]
 
   return wrapForm
diff --git a/src/menu/components/timeline/normal-timeline/index.scss b/src/menu/components/timeline/normal-timeline/index.scss
index 2f88860..51b98ae 100644
--- a/src/menu/components/timeline/normal-timeline/index.scss
+++ b/src/menu/components/timeline/normal-timeline/index.scss
@@ -23,7 +23,7 @@
   }
 
   .card-item {
-    overflow: hidden;
+    // overflow: hidden;
     position: relative;
     background-color: #ffffff;
     background-position: center center;
diff --git a/src/menu/components/tree/antd-tree/index.jsx b/src/menu/components/tree/antd-tree/index.jsx
index b093ad7..515d1d0 100644
--- a/src/menu/components/tree/antd-tree/index.jsx
+++ b/src/menu/components/tree/antd-tree/index.jsx
@@ -15,6 +15,7 @@
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -88,6 +89,7 @@
     card.name = card.wrap.name
 
     card.$c_ds = true
+    card.$c_ac = true
       
     card.errors = checkComponent(card)
 
@@ -160,6 +162,20 @@
     MKEmitter.emit('addButton', card.uuid, newcard)
   }
 
+  pasteComponent = (res, resolve) => {
+    if (res.style) {
+      delete res.style.width
+      delete res.style.float
+    }
+
+    res.Ot = res.Ot === 'requiredSgl' ? 'requiredSgl' : 'notRequired'
+
+    resolve({status: true})
+
+    res.uuid = Utils.getuuid()
+    this.addButton(res)
+  }
+
   setSubConfig = (item) => {
     const { card, appType } = this.state
     let btn = fromJS(item).toJS()
@@ -180,9 +196,9 @@
   }
 
   getWrapForms = () => {
-    const { wrap, columns } = this.state.card
+    const { wrap, columns, action } = this.state.card
 
-    return getWrapForm(wrap, columns)
+    return getWrapForm(wrap, columns, action.findIndex(item => item.Ot === 'requiredSgl') > -1)
   }
 
   updateWrap = (res) => {
@@ -205,6 +221,9 @@
   render() {
     const { card } = this.state
     let _style = resetStyle(card.style)
+    if (card.wrap.lineHeight) {
+      _style['--mk-tree-line-height'] = card.wrap.lineHeight + 'px'
+    }
 
     return (
       <div className="menu-tree-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
@@ -217,6 +236,7 @@
               <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
             </NormalForm>
             <CopyComponent type="tree" card={card}/>
+            <PasteComponent options={['action']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/tree/antd-tree/index.scss b/src/menu/components/tree/antd-tree/index.scss
index 20df956..37f6cfb 100644
--- a/src/menu/components/tree/antd-tree/index.scss
+++ b/src/menu/components/tree/antd-tree/index.scss
@@ -7,6 +7,7 @@
   background-size: cover;
   min-height: 100px;
   overflow-y: auto;
+  --mk-tree-line-height: 24px;
 
   .anticon-tool {
     position: absolute;
@@ -28,6 +29,15 @@
   .model-menu-action-list:not(.length0) {
     margin: 10px 0px;
   }
+  .model-menu-action-list {
+    .ant-btn {
+      border-width: 0px;
+    }
+  }
+  .ant-tree li .ant-tree-node-content-wrapper, .ant-tree li span.ant-tree-switcher, .ant-tree li span.ant-tree-iconEle {
+    height: var(--mk-tree-line-height);
+    line-height: var(--mk-tree-line-height);
+  }
 }
 .menu-tree-box::after {
   display: block;
diff --git a/src/menu/components/tree/antd-tree/options.jsx b/src/menu/components/tree/antd-tree/options.jsx
index d8b6a7e..54c8c0d 100644
--- a/src/menu/components/tree/antd-tree/options.jsx
+++ b/src/menu/components/tree/antd-tree/options.jsx
@@ -1,7 +1,7 @@
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
-export default function (wrap, columns = []) {
+export default function (wrap, columns = [], hasLineAction) {
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
   let ispop = sessionStorage.getItem('editMenuType') === 'popview'
@@ -79,6 +79,16 @@
       required: true
     },
     {
+      type: 'number',
+      field: 'lineHeight',
+      label: '琛岄珮',
+      initval: wrap.lineHeight || 24,
+      min: 24,
+      max: 200,
+      precision: 0,
+      required: true
+    },
+    {
       type: 'radio',
       field: 'showIcon',
       label: '鍥炬爣',
@@ -124,6 +134,19 @@
     },
     {
       type: 'radio',
+      field: 'actShow',
+      label: '鎸夐挳鏄剧ず',
+      initval: wrap.actShow || 'dropdown',
+      tooltip: '閫夋嫨鍗曡鎸夐挳鐨勬樉绀烘柟寮忋��',
+      required: false,
+      forbid: !hasLineAction,
+      options: [
+        {value: 'dropdown', label: '涓嬫媺'},
+        {value: 'line', label: '琛屽唴'},
+      ]
+    },
+    {
+      type: 'radio',
       field: 'permission',
       label: '鏉冮檺楠岃瘉',
       initval: wrap.permission || 'false',
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index 0121e76..10fedf6 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -173,7 +173,9 @@
           return item
         })
 
-        res.columns.reverse()
+        if (!config.fixedCol) {
+          res.columns.reverse()
+        }
       }
 
       let maxScript = 0
diff --git a/src/menu/datasource/verifycard/customscript/index.jsx b/src/menu/datasource/verifycard/customscript/index.jsx
index 489c1f6..545d436 100644
--- a/src/menu/datasource/verifycard/customscript/index.jsx
+++ b/src/menu/datasource/verifycard/customscript/index.jsx
@@ -210,7 +210,7 @@
   }
 
   render() {
-    const { systemScripts, setting, type } = this.props
+    const { systemScripts, setting, type, hasExtend } = this.props
     const { getFieldDecorator } = this.props.form
     const { usefulFields, skip } = this.state
 
@@ -226,7 +226,7 @@
           </Col> : null}
           <Col span={18}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0}}>
-              ErrorCode, retmsg
+              errorcode, retmsg
               <span style={{marginLeft: 25}}>
                 鎴愬姛锛�
                 <span className="error-val" onClick={() => {this.showError('S')}}> S </span>銆�
@@ -245,7 +245,7 @@
             <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={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><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' : ''}</Tooltip>
+              <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎺掑簭銆佸垎椤典互鍙婃悳绱㈡潯浠跺彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆備娇鐢ˊpageSize@鎴朄orderBy@浠h〃鑷畾涔夊垎椤碉紝鎬绘暟璇蜂互mk_total杩斿洖銆�'}>orderBy, pageSize, pageIndex{usefulFields ? ', ' + usefulFields : ''}{type === 'calendar' ? ', mk_year' : ''}{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/index.jsx b/src/menu/datasource/verifycard/index.jsx
index ceabb28..8fb10d0 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -48,6 +48,7 @@
     systemScripts: [],
     median: {},
     visible: false,
+    editLineId: '',
     pvisible: false,
     reload: false,
     script: null,
@@ -215,9 +216,11 @@
     let columns = config.columns ? fromJS(config.columns).toJS() : []
     let subColumns = config.subColumns ? fromJS(config.subColumns).toJS() : []
 
-    columns.reverse()
+    if (!config.fixedCol) {
+      columns.reverse()
+    }
     subColumns.reverse()
-
+    
     columns.forEach(col => {
       if (!col.datatype) return
       if (/^nvarchar/.test(col.datatype)) {
@@ -677,7 +680,8 @@
       if (config.subtype === 'dualdatacard') {
         _columns = [...columns, ...subColumns]
       }
-      let r = SettingUtils.getDebugSql(setting, _scripts, _columns, searches, config.type)
+
+      let r = SettingUtils.getDebugSql(setting, _scripts, _columns, searches, config.subtype, config.hasExtend)
 
       let _debugId = md5(r.sql)
       
@@ -809,7 +813,9 @@
       return
     }
 
+    let editLineId = ''
     if (script) {
+      editLineId = script.uuid
       _scripts = _scripts.map(item => {
         if (script.uuid === item.uuid) {
           item.sql = scriptValue
@@ -824,10 +830,11 @@
         status: 'true'
       }
 
+      editLineId = _script.uuid
       _scripts.push(_script)
     }
 
-    this.setState({loading: true})
+    this.setState({loading: true, editLineId})
 
     this.sqlverify(() => {this.setState({scripts: _scripts, script: null, scriptValue: '', loading: false})}, () => {this.setState({loading: false})}, 'script', _scripts)
   }
@@ -954,7 +961,9 @@
   }
 
   copyColumns = () => {
-    const { columns } = this.state
+    const { config } = this.props
+    const { columns, setting } = this.state
+
     let m = []
     let n = []
     let s = []
@@ -977,9 +986,57 @@
       console.info('select ' + s.join(', '))
     }
 
+    let extend = ''
+    if (config.hasExtend) {
+      extend = []
+      let mapCol = (cols) => {
+        cols.forEach(col => {
+          if (col.type === 'extend') {
+            let datatype = 'Nvarchar(50)'
+            columns.forEach(c => {
+              if (c.field === col.field) {
+                datatype = c.datatype
+              }
+            })
+            for (let i = 1; i < col.quota; i++) {
+              extend.push(`${col.field}${i} ${datatype}`)
+            }
+          } else if (col.type === 'colspan' && col.subcols) {
+            mapCol(col.subcols)
+          }
+        })
+      }
+      mapCol(config.cols)
+      extend = `
+      /* 鎵╁睍鍒楀瓧娈� */
+      /* ${extend.join(',')} */
+      `
+    }
+
     let oInput = document.createElement('input')
-    oInput.value = `/*${m.join(',')}*/
-      ${n.join(',')}`
+    oInput.value = `create table #${setting.tableName || 'tb'}
+    (${m.join(',')},sort_id INT IDENTITY(1,1))
+    insert into #${setting.tableName || 'tb'}
+    (${n.join(',')})
+    select ${n.join(',')}
+    from ${setting.dataresource ? `(${setting.dataresource.replace(/\n/g, ' ')}) tb` : setting.tableName || 'tb'}
+    order by @orderBy@
+    
+    declare @mk_total int
+    set @mk_total = 0
+      
+    select @mk_total = count(1) from #${setting.tableName || 'tb'}
+      declare @pageIndex_top int 
+      set @pageIndex_top=(@pageIndex@-1)*@pageSize@ 
+      
+      if @mk_total > @pageIndex@*@pageSize@
+        delete #${setting.tableName || 'tb'} where sort_id > @pageIndex@*@pageSize@ 
+      
+      if @pageIndex_top > 0
+        delete #${setting.tableName || 'tb'} where sort_id <= @pageIndex_top
+
+    drop table #${setting.tableName || 'tb'}${extend}`
+
     document.body.appendChild(oInput)
     oInput.select()
     document.execCommand('Copy')
@@ -1106,7 +1163,7 @@
 
   render() {
     const { config } = this.props
-    const { columns, subColumns, median, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue, searchKey } = this.state
+    const { columns, subColumns, median, setting, scripts, colColumns, scriptsColumns, activeKey, loading, searches, defaultsql, visible, pvisible, reload, script, scriptValue, searchKey, editLineId } = this.state
 
     return (
       <div className="model-data-source-wrap">
@@ -1130,7 +1187,7 @@
               wrappedComponentRef={(inst) => this.settingForm = inst}
             /> : null}
           </TabPane>
-          {config.subtype !== 'basetable' ? <TabPane tab={
+          {!['basetable', 'invoice', 'invTable'].includes(config.subtype) ? <TabPane tab={
             <span>
               瀛楁闆�
               {columns.length ? <span className="count-tip">{columns.length}</span> : null}
@@ -1186,10 +1243,11 @@
                 })
                 return
               }
-              this.setState({visible: true, script: null, scriptValue: ''})
+              this.setState({visible: true, script: null, scriptValue: '', editLineId: ''})
             }}/> : null}
             <CustomScriptsForm
               type={config.type}
+              hasExtend={config.hasExtend}
               setting={setting}
               searches={searches}
               defaultsql={defaultsql}
@@ -1236,8 +1294,14 @@
                   </div>
                 )
               } else {
+                let sign = ''
+                if (script && script.uuid === item.uuid) {
+                  sign = 'active'
+                } else if (editLineId === item.uuid) {
+                  sign = 'edited'
+                }
                 return (
-                  <div className={'script-item ' + (script && script.uuid === item.uuid ? 'active' : '') } key={item.uuid}>
+                  <div className={'script-item ' + sign} key={item.uuid}>
                     <div style={{cursor: 'pointer'}} onClick={() => {
                       this.setState({script: item, scriptValue: item.sql})
                     }}>
diff --git a/src/menu/datasource/verifycard/index.scss b/src/menu/datasource/verifycard/index.scss
index e791cda..308bfb9 100644
--- a/src/menu/datasource/verifycard/index.scss
+++ b/src/menu/datasource/verifycard/index.scss
@@ -195,6 +195,11 @@
         .script-item.active {
           background-color: #bae7ff;
         }
+        .script-item.edited {
+          .ant-typography {
+            color: #1890ff;
+          }
+        }
         .ant-typography {
           margin-bottom: 5px;
         }
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index d52d420..560e5d9 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -375,7 +375,7 @@
               </Form.Item>
             </Col> : null}
             {setting.interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
-              {window.GLOB.process ? <span className="process-btn" onClick={this.addProcess}>宸ヤ綔娴�</span> : null}
+              {window.GLOB.process && !['invoice', 'invTable'].includes(config.subtype) ? <span className="process-btn" onClick={this.addProcess}>宸ヤ綔娴�</span> : null}
               <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
                 <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''銆俙}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -409,7 +409,7 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            <Col span={8}>
+            {!['invTable'].includes(config.subtype) ? <Col span={8}>
               <Form.Item label="涓婚敭">
                 {getFieldDecorator('primaryKey', {
                   initialValue: setting.primaryKey || ''
@@ -423,7 +423,7 @@
                   </Select>
                 )}
               </Form.Item>
-            </Col>
+            </Col> : null}
             {/* 鏁扮粍鏁版嵁锛岄渶璁剧疆鎺掑簭瑙勫垯 */}
             {config.format === 'array' ? <Col span={8}>
               <Form.Item label={
@@ -454,7 +454,7 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') && MenuType !== 'billPrint' ? <Col span={8}>
+            {!['balcony', 'menubar', 'commonbar', 'tabbar', 'invTable'].includes(config.subtype) && (!config.wrap || config.wrap.supType !== 'multi') && MenuType !== 'billPrint' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -516,7 +516,7 @@
               </Form.Item>
             </Col> : null}
             {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */}
-            {!['navbar', 'interface', 'calendar'].includes(config.type) && !['editable', 'basetable', 'dualdatacard'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') && setting.interType === 'system' && setting.onload !== 'false' ? <Col span={8}>
+            {!['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瀛楃鏃舵棤鏁堛��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -533,7 +533,7 @@
                 )}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) && !['basetable'].includes(config.subtype) ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar'].includes(config.type) && !['basetable', 'invoice', 'invTable'].includes(config.subtype) ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={config.type === 'interface' ? '鍗曠嫭鎼滅储缁勪欢鍙綔涓哄叕鍏辨暟鎹簮鐨勬悳绱㈡潯浠躲��' : '浼樺厛浣跨敤鍚岀骇鐨勬悳绱㈡潯浠剁粍浠讹紝鍚岀骇鎼滅储涓嶅瓨鍦ㄦ椂锛屼緷娆″悜涓婇�夊彇锛屼笌褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵竴鍚岀敤浣滄暟鎹繃婊わ紙褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵紭鍏堬級銆�'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -683,8 +683,7 @@
           wrapClassName="mk-flow-type"
           visible={visible}
           width={400}
-          maskClosable={false}
-          closable={false}
+          onCancel={() => this.setState({visible: false})}
           footer={[
             <Button key="cancel" className="mk-green" onClick={() => this.execAddProcess('flowstart')}>鍙戣捣</Button>,
             <Button key="confirm" className="mk-primary" onClick={() => this.execAddProcess('flowcheck')}>瀹℃壒</Button>
diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx
index b443500..67b552d 100644
--- a/src/menu/datasource/verifycard/utils.jsx
+++ b/src/menu/datasource/verifycard/utils.jsx
@@ -9,7 +9,7 @@
    * @return {Object}  setting       椤甸潰璁剧疆
    * @return {Array}   columns       鏄剧ず瀛楁
    */
-  static getDebugSql (setting, scripts, columns, searches = [], type) {
+  static getDebugSql (setting, scripts, columns, searches = [], type, hasExtend) {
     let sql = ''
     let error = ''
     let _dataresource = ''
@@ -75,10 +75,13 @@
       {reg: /@sum\$|\$sum@/ig, value: ''},
     ]
 
-    if (window.GLOB.process) {
+    if (window.GLOB.process && type !== 'invoice') {
       regs.push({reg: /@works_flow_code@/ig, value: `'${getuuid()}'`})
     }
 
+    if (hasExtend) {
+      regs.push({reg: /@mk_time@/ig, value: '2024-04-29 17:20:00'})
+    }
     if (type === 'calendar') {
       regs.push({reg: /@mk_year@/ig, value: '2024'})
     }
@@ -101,7 +104,7 @@
       `
     }
 
-    if (window.GLOB.urlFields) {
+    if (window.GLOB.urlFields && type !== 'invoice') {
       window.GLOB.urlFields.forEach(field => {
         let reg = new RegExp('@' + field + '@', 'ig')
         _dataresource = _dataresource.replace(reg, `'0'`)
diff --git a/src/menu/debug/index.jsx b/src/menu/debug/index.jsx
index 9b48dde..09c2038 100644
--- a/src/menu/debug/index.jsx
+++ b/src/menu/debug/index.jsx
@@ -770,7 +770,7 @@
     }
     _sql = `Declare @tbid nvarchar(50),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50),@ModularDetailCode nvarchar(50), @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@mk_deleted int,@bid nvarchar(50)${_declarefields}
       `
-  
+
     let userName = 'User_Name'
     let fullName = 'Full_Name'
     let RoleID = 'role_id'
@@ -1281,15 +1281,52 @@
       let detailId = '0'
   
       if (verify.flowSql === 'true') {
-        _sql += `
-        /* 宸ヤ綔娴侀粯璁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,upid)
-        select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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@
-        `
+        if (verify.flowType === 'start') {
+          _sql += `
+            /* 宸ヤ綔娴侀粯璁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 {
+          _sql += `
+            /* 宸ヤ綔娴侀粯璁ql */
+            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 : ''}
+            
+            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
+          `
+        }
+      }
+
+      if (_backCustomScript) {
+        _sql += _backCustomScript
       }
   
       _sql = _sql.replace(/@start_type@/ig, `'寮�濮�'`)
@@ -1297,6 +1334,7 @@
       _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, `''`)
@@ -1305,9 +1343,7 @@
       _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
       _sql = _sql.replace(/@work_group@/ig, `'mk'`)
       _sql = _sql.replace(/@work_grade@/ig, `'0'`)
-    }
-  
-    if (_backCustomScript) {
+    } else if (_backCustomScript) {
       _sql += _backCustomScript
     }
   
@@ -1494,7 +1530,7 @@
       `
     }
 
-    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50) )
+    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),BID nvarchar(50))
       Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)
       
       Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
@@ -1683,7 +1719,7 @@
       `
     }
 
-    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
+    sql = `create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
       Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)
       
       Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
@@ -1709,11 +1745,10 @@
     let item = {setting: {}, columns: [], search: []}
 
     btn.verify.columns.forEach(col => {
-      if (col.Column && col.Column !== '$Index') {
-        item.columns.push({
-          field: col.Column
-        })
-      }
+      if (col.output === 'false' || !col.Column || col.Column === '$Index') return
+      item.columns.push({
+        field: col.Column
+      })
     })
 
     if (btn.verify.useSearch !== 'false') {
@@ -1857,6 +1892,9 @@
       { reg: /@typename@/ig, value: `'admin'`},
     )
 
+    if (item.hasExtend) {
+      regs.push({reg: /@mk_time@/ig, value: '2024-04-29 17:20:00'})
+    }
     if (item.type === 'calendar') {
       regoptions.push({ reg: /@mk_year@/ig, value: '2024' })
     }
diff --git a/src/menu/header/index.jsx b/src/menu/header/index.jsx
index 9617900..f7a1c6d 100644
--- a/src/menu/header/index.jsx
+++ b/src/menu/header/index.jsx
@@ -7,15 +7,17 @@
 class MenuHeader extends Component {
   state = {
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
-    userName: sessionStorage.getItem('CloudUserName')
+    userName: sessionStorage.getItem('CloudUserName'),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   render () {
     const { menuName } = this.props
+    const { logo } = this.state
 
     return (
       <header className="menu-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="menu-name">{menuName}</div>
         <div className="header-setting">
           <img src={this.state.avatar} alt=""/>
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index b56942a..47269bf 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -30,6 +30,7 @@
 const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
 const Voucher = asyncComponent(() => import('@/menu/components/module/voucher'))
 const Account = asyncComponent(() => import('@/menu/components/module/account'))
+const Invoice = asyncComponent(() => import('@/menu/components/module/invoice'))
 const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
 const AntvG6 = asyncComponent(() => import('@/menu/components/chart/antv-G6'))
 const AntvX6 = asyncComponent(() => import('@/menu/components/chart/antv-X6'))
@@ -135,6 +136,8 @@
       return (<Voucher card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'module' && card.subtype === 'account') {
       return (<Account card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'module' && card.subtype === 'invoice') {
+      return (<Invoice card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index 8bb149f..6388269 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -135,7 +135,7 @@
         })
       }
 
-      if (item.type === 'switch' || item.type === 'check') {
+      if (['switch', 'check', 'popSelect'].includes(item.type)) {
         _linksupFields.push({
           field: item.field,
           label: item.label
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index d73bd57..3de73e1 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -76,8 +76,16 @@
     height: 100%;
     overflow-y: hidden;
     background: #ffffff;
-    .ant-card-head {
-      min-height: 44px;
+    .ant-card {
+      padding-top: 45px;
+      .ant-card-head {
+        min-height: 44px;
+        position: fixed;
+        width: calc(100vw - 235px);
+        top: 48px;
+        z-index: 12;
+        background: #ffffff;
+      }
     }
     .ant-card-head-title {
       padding: 5px 0;
@@ -265,12 +273,6 @@
         top: 5px;
         padding: 10px;
         cursor: pointer;
-      }
-      .paste-Icon {
-        position: absolute;
-        font-size: 16px;
-        right: 15px;
-        top: 65px;
       }
     }
   }
diff --git a/src/menu/modulecell/index.jsx b/src/menu/modulecell/index.jsx
index 4bc5e54..f587103 100644
--- a/src/menu/modulecell/index.jsx
+++ b/src/menu/modulecell/index.jsx
@@ -22,6 +22,7 @@
           { value: 'qrcode', text: '浜岀淮鐮�', type: 'action', class: 'element', $init: true},
           { value: 'currentDate', text: '褰撳墠鏃堕棿', type: 'action', class: 'element', $init: true},
           { value: 'formula', text: '鍏紡', type: 'action', class: 'element', $init: true},
+          { value: 'tag', text: '鏍囩', type: 'action', class: 'element', $init: true},
           { value: 'color', text: '棰滆壊', type: 'action', class: 'element', $init: true},
           { value: 'sequence', text: '搴忓彿', type: 'action', class: 'element', $init: true }
         ]
diff --git a/src/menu/modulesource/option.jsx b/src/menu/modulesource/option.jsx
index 1607a5a..9013a15 100644
--- a/src/menu/modulesource/option.jsx
+++ b/src/menu/modulesource/option.jsx
@@ -32,6 +32,7 @@
 import Voucher from '@/assets/mobimg/voucher.png'
 import Account from '@/assets/mobimg/account.png'
 import canlendar from '@/assets/mobimg/canlendar.png'
+import Invoice from '@/assets/img/invoice.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -72,4 +73,5 @@
   { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: Account, component: 'module', subtype: 'account', title: '璐﹀', width: 24, forbid: ['billPrint'] },
   { type: 'menu', url: Voucher, component: 'module', subtype: 'voucher', title: '鍑瘉', width: 24, forbid: ['billPrint'] },
+  { type: 'menu', url: Invoice, component: 'module', subtype: 'invoice', title: '鍙戠エ', width: 24, forbid: ['billPrint'] },
 ]
diff --git a/src/menu/stylecontroller/index.jsx b/src/menu/stylecontroller/index.jsx
index 89f5ca9..c5ed9e0 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 } from 'antd'
+import { Collapse, Form, Col, InputNumber, Input, Select, Radio, Drawer, Button, message, Checkbox } from 'antd'
 import {
   ColumnHeightOutlined,
   FontSizeOutlined,
@@ -53,7 +53,8 @@
     backgroundImage: '',
     options: [],
     borposition: 'outer',
-    type: ''
+    type: '',
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   callback = null
@@ -130,30 +131,37 @@
   onCloseDrawer = () => {
     let card = fromJS(this.state.card).toJS()
 
-    let check = false
-    if (card.borderWidth === '0px') {
+    if (card.borderWidth === '0px' || !card.borderWidth) {
       delete card.borderWidth
       delete card.borderColor
-      check = true
-    } else if (card.borderLeftWidth === '0px') {
-      delete card.borderLeftWidth
-      delete card.borderLeftColor
-      check = true
-    } else if (card.borderRightWidth === '0px') {
-      delete card.borderRightWidth
-      delete card.borderRightColor
-      check = true
-    } else if (card.borderTopWidth === '0px') {
-      delete card.borderTopWidth
-      delete card.borderTopColor
-      check = true
-    } else if (card.borderBottomWidth === '0px') {
-      delete card.borderBottomWidth
-      delete card.borderBottomColor
-      check = true
     }
 
-    if (check) {
+    if (card.borderLeftWidth === '0px' || !card.borderLeftWidth) {
+      delete card.borderLeftWidth
+      delete card.borderLeftColor
+    }
+    if (card.borderRightWidth === '0px' || !card.borderRightWidth) {
+      delete card.borderRightWidth
+      delete card.borderRightColor
+    }
+    if (card.borderTopWidth === '0px' || !card.borderTopWidth) {
+      delete card.borderTopWidth
+      delete card.borderTopColor
+    }
+    if (card.borderBottomWidth === '0px' || !card.borderBottomWidth) {
+      delete card.borderBottomWidth
+      delete card.borderBottomColor
+    }
+
+    if (/0px 0px 0px | transparent/.test(card.boxShadow)) {
+      delete card.hShadow
+      delete card.vShadow
+      delete card.shadowBlur
+      delete card.shadowColor
+      delete card.boxShadow
+    }
+
+    if (!is(fromJS(this.state.card), fromJS(card))) {
       this.callback && this.callback(card)
     }
 
@@ -285,7 +293,7 @@
   changeShadowColor = (val) => {
     const { card } = this.state
 
-    let boxShadow = `${card.hShadow || '0px'} ${card.vShadow || '0px'} ${card.shadowBlur || '0px'} ${val}`
+    let boxShadow = `${card.hShadow || '0px'} ${card.vShadow || '0px'} ${card.shadowBlur || '0px'} ${val || 'transparent'}`
 
     this.updateStyle({shadowColor: val, boxShadow})
   }
@@ -561,7 +569,7 @@
   }
 
   render () {
-    const { card, options, backgroundImage, borposition, fonts, type } = this.state
+    const { card, options, backgroundImage, borposition, fonts, type, logo } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -577,7 +585,7 @@
       <Drawer
         title={
           <div className="header-logo">
-            <img src={MainLogo} alt=""/>
+            <img src={logo} alt=""/>
           </div>
         }
         placement="left"
@@ -716,6 +724,25 @@
                       <Radio.Button value="line-through"><StrikethroughOutlined title="涓垝绾�"/></Radio.Button>
                       <Radio.Button value="overline" style={{textDecoration: 'overline'}}><span title="涓婂垝绾�">O</span></Radio.Button>
                     </Radio.Group>
+                  </Form.Item>
+                </Col> : null}
+                {options.includes('fontFamily') ? <Col span={24}>
+                  <Form.Item
+                    colon={false}
+                    label=" "
+                    labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
+                  >
+                    <Checkbox.Group options={[
+                      { label: '寰蒋闆呴粦', value: 'Microsoft YaHei' },
+                      { label: '瀹嬩綋', value: 'Simsun' },
+                      { label: '榛戜綋', value: 'Simhei' },
+                      { label: '浠垮畫', value: 'FangSong' },
+                      { label: '妤蜂綋', value: 'KaiTi' },
+                      // { label: 'Helvetica', value: 'Helvetica' },
+                      // { label: 'Arial', value: 'Arial' },
+                      // { label: 'Verdana', value: 'Verdana' },
+                      // { label: 'Georgia', value: 'Georgia' },
+                    ]} defaultValue={card.fontFamily} onChange={(val) => this.changeNormalStyle(val, 'fontFamily')} />
                   </Form.Item>
                 </Col> : null}
               </Panel> : null}
@@ -865,11 +892,11 @@
                     label={<ColumnWidthOutlined title="杈规瀹藉害"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    {borposition === 'outer' ? <StyleInput defaultValue={card.borderWidth || '0px'} options={['px']} onChange={this.changeBorderWidth}/> : null}
-                    {borposition === 'left' ? <StyleInput defaultValue={card.borderLeftWidth || '0px'} options={['px']} onChange={this.changeBorderWidth}/> : null}
-                    {borposition === 'right' ? <StyleInput defaultValue={card.borderRightWidth || '0px'} options={['px']} onChange={this.changeBorderWidth}/> : null}
-                    {borposition === 'top' ? <StyleInput defaultValue={card.borderTopWidth || '0px'} options={['px']} onChange={this.changeBorderWidth}/> : null}
-                    {borposition === 'bottom' ? <StyleInput defaultValue={card.borderBottomWidth || '0px'} options={['px']} onChange={this.changeBorderWidth}/> : null}
+                    {borposition === 'outer' ? <StyleInput defaultValue={card.borderWidth || ''} options={['px']} onChange={this.changeBorderWidth}/> : null}
+                    {borposition === 'left' ? <StyleInput defaultValue={card.borderLeftWidth || ''} options={['px']} onChange={this.changeBorderWidth}/> : null}
+                    {borposition === 'right' ? <StyleInput defaultValue={card.borderRightWidth || ''} options={['px']} onChange={this.changeBorderWidth}/> : null}
+                    {borposition === 'top' ? <StyleInput defaultValue={card.borderTopWidth || ''} options={['px']} onChange={this.changeBorderWidth}/> : null}
+                    {borposition === 'bottom' ? <StyleInput defaultValue={card.borderBottomWidth || ''} options={['px']} onChange={this.changeBorderWidth}/> : null}
                   </Form.Item>
                 </Col>
                 <Col span={24}>
@@ -878,11 +905,11 @@
                     label={<BgColorsOutlined title="杈规棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    {borposition === 'outer' ? <ColorSketch value={card.borderColor || ''} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'left' ? <ColorSketch value={card.borderLeftColor || ''} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'right' ? <ColorSketch value={card.borderRightColor || ''} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'top' ? <ColorSketch value={card.borderTopColor || ''} onChange={this.changeBorderColor} /> : null}
-                    {borposition === 'bottom' ? <ColorSketch value={card.borderBottomColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'outer' ? <ColorSketch allowClear={true} value={card.borderColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'left' ? <ColorSketch allowClear={true} value={card.borderLeftColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'right' ? <ColorSketch allowClear={true} value={card.borderRightColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'top' ? <ColorSketch allowClear={true} value={card.borderTopColor || ''} onChange={this.changeBorderColor} /> : null}
+                    {borposition === 'bottom' ? <ColorSketch allowClear={true} value={card.borderBottomColor || ''} onChange={this.changeBorderColor} /> : null}
                   </Form.Item>
                   <Form.Item
                     colon={false}
@@ -909,7 +936,7 @@
                     label={<BgColorsOutlined title="闃村奖棰滆壊"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
-                    <ColorSketch value={card.shadowColor || ''} onChange={this.changeShadowColor} />
+                    <ColorSketch allowClear={true} value={card.shadowColor || ''} onChange={this.changeShadowColor} />
                   </Form.Item>
                   <Form.Item
                     colon={false}
@@ -1068,7 +1095,7 @@
                 <Col span={24}>
                   <Form.Item
                     colon={false}
-                    label={<SwapOutlined title="娴姩"/>}
+                    label={<SwapOutlined title="鏄剧ず"/>}
                     labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                   >
                     <Radio.Group style={{whiteSpace: 'nowrap'}} defaultValue={card.display || 'block'} onChange={(e) => this.changeNormalStyle(e.target.value, 'display')}>
diff --git a/src/menu/stylecontroller/index.scss b/src/menu/stylecontroller/index.scss
index 8940758..df5ab73 100644
--- a/src/menu/stylecontroller/index.scss
+++ b/src/menu/stylecontroller/index.scss
@@ -127,6 +127,22 @@
                   }
                 }
               }
+              .ant-checkbox-group {
+                margin-top: 10px;
+                .ant-checkbox-wrapper {
+                  color: rgba(255, 255, 255, 0.85);
+                  margin-right: 4px;
+                  margin-bottom: 2px;
+                  .ant-checkbox + span {
+                    padding-left: 6px;
+                  }
+                  .ant-checkbox:not(.ant-checkbox-checked) {
+                    .ant-checkbox-inner {
+                      background-color: rgba(255, 255, 255, 0.85);
+                    }
+                  }
+                }
+              }
             }
           }
         }
diff --git a/src/mob/components/topbar/normal-navbar/options.jsx b/src/mob/components/topbar/normal-navbar/options.jsx
index 33f0c7d..43cc169 100644
--- a/src/mob/components/topbar/normal-navbar/options.jsx
+++ b/src/mob/components/topbar/normal-navbar/options.jsx
@@ -184,7 +184,7 @@
       field: 'prefix',
       label: '鍓嶇紑',
       initval: wrap.prefix || '',
-      tooltip: '鎵爜淇℃伅灏嗕笌鍓嶇紑鎷兼帴鍚庢墽琛屻�傛敞锛氳烦杞彍鍗曢渶浠kbid寮�澶淬��',
+      tooltip: '鎵爜淇℃伅灏嗕笌鍓嶇紑鎷兼帴鍚庢墽琛屻�傛敞锛氳烦杞彍鍗曢渶浠kbid锛�:鎴�,锛夊紑澶达紝mkbid锛�:鎴�,锛夎烦杞悗灏嗚鍘婚櫎銆備緥濡傦細mkbid:123456 璺宠浆鍚庨〉闈ID涓� 123456銆�',
       required: false
     },
     {
diff --git a/src/mob/header/index.jsx b/src/mob/header/index.jsx
index 38c5863..6d61f1f 100644
--- a/src/mob/header/index.jsx
+++ b/src/mob/header/index.jsx
@@ -7,13 +7,16 @@
 class MobHeader extends Component {
   state = {
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
-    userName: sessionStorage.getItem('CloudUserName')
+    userName: sessionStorage.getItem('CloudUserName'),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   render () {
+    const { logo } = this.state
+
     return (
       <header className="mob-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="header-user">
           <img src={this.state.avatar} alt=""/>
           <span>
diff --git a/src/mob/searchconfig/index.jsx b/src/mob/searchconfig/index.jsx
index 716433e..e943736 100644
--- a/src/mob/searchconfig/index.jsx
+++ b/src/mob/searchconfig/index.jsx
@@ -228,7 +228,8 @@
           sqlVerifing: true
         })
 
-        let sql = res.dataSource
+        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
         
         let rduri = ''
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index 83f496c..a8c9ff9 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -45,7 +45,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { MenuID, MenuName } = this.props
+    const { MenuID, MenuName, param } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -148,8 +148,8 @@
         try { // 閰嶇疆淇℃伅瑙f瀽
           let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
           if (userConfig) {
-            shortcuts = userConfig.action
-            userConfig.printers.forEach(item => {
+            shortcuts = userConfig.action || []
+            userConfig.printers && userConfig.printers.forEach(item => {
               window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
             })
           }
@@ -161,9 +161,18 @@
       // 鏉冮檺杩囨护
       let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
       let skip = window.GLOB.mkHS
-      let param = this.props.param || {} // url鍙傛暟
+      let urlparam = {} // url鍙傛暟
+      if (param) {
+        Object.keys(param).forEach(key => {
+          if (/^\$/.test(key)) {
+            urlparam[key] = param[key]
+          } else {
+            urlparam[key.toLowerCase()] = param[key]
+          }
+        })
+      }
 
-      window.GLOB.CacheData.set(MenuID, param)
+      window.GLOB.CacheData.set(MenuID, urlparam)
 
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -181,7 +190,7 @@
       }
       if (config.urlFields) {
         config.urlFields.forEach(field => {
-          let val = `'${param[field] || ''}'`
+          let val = `'${urlparam[field.toLowerCase()] || ''}'`
           regs.push({
             reg: new RegExp('@' + field + '@', 'ig'),
             value: val
@@ -193,7 +202,7 @@
         regs.push({ reg: /@works_flow_code@/ig, value: `'${config.flow_code}'` })
       }
 
-      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, param, MenuID, config.MenuName, config.process === 'true')
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, skip, urlparam, MenuID, config.MenuName, config.process === 'true')
 
       let autoMatic = null
       if (config.autoMatic && config.autoMatic.enable === 'true') {
@@ -213,18 +222,6 @@
       config.components.forEach(component => {
         if (component.type === 'tabs') return
 
-        if (param.$searchkey) {
-          component.search = component.search.map(item => {
-            if (['text', 'select', 'link', 'checkcard'].includes(item.type) && param.$searchkey === item.field) {
-              item.initval = param.$searchval
-            }
-  
-            return item
-          })
-
-          component.$searches = Utils.initMainSearch(component.search)
-        }
-
         if (component.$searches.length) {
           component.$main = true
           
@@ -236,7 +233,7 @@
         }
       })
 
-      let BID = param.$BID || ''
+      let BID = urlparam.$BID || ''
 
       config.components = this.formatSetting(config.components, regs)
 
@@ -358,6 +355,14 @@
       // 鎼滅储鏉′欢鍒濆鍖�
       Utils.initSearchVal(item)
 
+      if (urlparam.$searchkey) {
+        item.search.forEach(cell => {
+          if (urlparam.$searchkey === cell.field.toLowerCase() && ['text', 'select', 'link', 'checkcard'].includes(cell.type)) {
+            cell.initval = urlparam.$searchval
+          }
+        })
+      }
+
       item.$searches = Utils.initMainSearch(item.search)
 
       let statFields = []
@@ -371,7 +376,10 @@
             col.type = 'custom'
           }
           
-          if (col.type === 'number') {
+          if (col.type === 'index') {
+            col.field = '$Index'
+            col.type = 'text'
+          } else if (col.type === 'number') {
             if (col.sum === 'true') {
               statFields.push(col)
             }
@@ -397,7 +405,7 @@
                   cell = this.getPrinter(cell, item.uuid)
                 }
 
-                return skip || permAction[cell.uuid]
+                return skip || permAction[cell.uuid] || cell.permission === 'false'
               } else if (['text', 'number', 'formula'].includes(cell.eleType)) {
                 if (!cell.height) {
                   cell.innerHeight = 'auto'
@@ -410,8 +418,19 @@
                 }
               }
 
+              if (cell.linkmenu && cell.linkmenu.length > 0) {
+                let menu_id = cell.linkmenu.pop()
+                cell.linkThdMenu = window.GLOB.mkThdMenus.get(menu_id) || ''
+                if (!cell.linkThdMenu) {
+                  cell.link = ''
+                }
+              }
+
               if (cell.marks && cell.marks.length === 0) {
                 cell.marks = null
+              }
+              if (cell.anchors && cell.anchors.length === 0) {
+                cell.anchors = null
               }
 
               return true
@@ -453,7 +472,7 @@
             cell = this.getPrinter(cell, item.uuid)
           }
 
-          return skip || permAction[cell.uuid]
+          return skip || permAction[cell.uuid] || cell.permission === 'false'
         })
       }
       
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index 78fd480..e94c925 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -138,8 +138,8 @@
               })
             })
           } else if (userConfig) {
-            shortcuts = userConfig.action
-            userConfig.printers.forEach(item => {
+            shortcuts = userConfig.action || []
+            userConfig.printers && userConfig.printers.forEach(item => {
               window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
             })
           }
@@ -209,7 +209,7 @@
 
       // 瀛楁閫忚鍙婂繀濉爣蹇�
       config.search = config.search.map(item => {
-        if (['text', 'select', 'link', 'checkcard'].includes(item.type) && param && param.$searchkey === item.field) {
+        if (['text', 'select', 'link', 'checkcard'].includes(item.type) && param && param.$searchkey === item.field.toLowerCase()) {
           item.initval = param.$searchval
         }
         return item
@@ -295,6 +295,7 @@
 
       let _actions = []      // 宸ュ叿鏍忔寜閽�
       let _operations = []   // 鎿嶄綔鍒楁寜閽紙瀛樺湪鏃讹級
+      let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#E7E7EF', default: 'rgba(0, 0, 0, 0.65)' }
 
       config.action.forEach(item => {
         item.logLabel = MenuName + '-' + item.label // 鐢ㄤ簬sPC_TableData_InUpDe璁板綍鎿嶄綔鎸夐挳
@@ -345,11 +346,26 @@
             item.controlVals = [(item.controlVal || '')]
           }
         }
-        
+
+        item.show = 'button'
+
+        let _c = item.class ? item.class.replace('border-', '') : ''
+        let color = colors[_c] || '#1890ff'
+
         if (item.position === 'toolbar') {
           item.$toolbtn = true
+
+          if (item.class === 'default') {
+            item.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: '#fff', borderColor: '#d9d9d9', marginRight: '15px'}
+          } else if (item.class.indexOf('border') > -1) {
+            item.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
+          } else {
+            item.style = {color: item.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+          }
+
           _actions.push(item)
         } else if (item.position === 'grid') {
+          item.style = {color: color, backgroundColor: 'transparent', borderColor: 'transparent'}
           _operations.push(item)
         }
       })
@@ -587,6 +603,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, search, _orderBy, pageIndex, pageSize, BID)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
 
     this.getStatFieldsValue()
@@ -678,6 +696,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, search, _orderBy, pageIndex, pageSize, BID, id)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
diff --git a/src/tabviews/custom/components/calendar/index.jsx b/src/tabviews/custom/components/calendar/index.jsx
index 764dd9b..c8ea014 100644
--- a/src/tabviews/custom/components/calendar/index.jsx
+++ b/src/tabviews/custom/components/calendar/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Modal } from 'antd'
+import { Spin } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
@@ -180,8 +180,8 @@
 
     if (config.uuid !== menuId) return
 
-    if (position === 'mainline' && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -264,36 +264,13 @@
         loading: false
       })
       
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx
index d3b0ce0..3b9b8f7 100644
--- a/src/tabviews/custom/components/card/balcony/index.jsx
+++ b/src/tabviews/custom/components/card/balcony/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Checkbox, Modal } from 'antd'
+import { Spin, Checkbox } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -71,12 +71,26 @@
         _data = window.GLOB.CacheData.get(_config.wrap.publicId)
         _data = fromJS(_data).toJS()
       }
+    } else {
+      _config.elements.forEach(item => {
+        if (item.eleType === 'button') return
+        if (item.datatype === 'dynamic' && item.field) {
+          item.field = item.field.toLowerCase()
+        }
+      })
     }
 
     _data.$$BID = BID || ''
     _data.$$BData = BData || ''
     if (_config.setting.primaryKey) {
       _data.$$uuid = _data[_config.setting.primaryKey] || ''
+    }
+
+    if (_config.wrap.datatype === 'static' && BData) {
+      Object.keys(BData).forEach(key => {
+        if (/\$/.test(key)) return
+        _data[key.toLowerCase()] = BData[key]
+      })
     }
 
     if (!_config.style.position) {
@@ -273,8 +287,8 @@
 
       this.loadData()
     } else {
-      if ((position === 'mainline' || position === 'popclose') && config.wrap.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-        MKEmitter.emit('reloadData', config.wrap.supModule, BID)
+      if (['mainline', 'maingrid', 'popclose'].includes(position) && config.wrap.supModule) {
+        MKEmitter.emit('reloadData', config.wrap.supModule, position === 'maingrid' ? '' : BID)
       } else {
         this.loadData()
       }
@@ -359,8 +373,16 @@
     }
     
     if (config.wrap.datatype === 'static') {
+      let _data = {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()}
+      if (BData) {
+        Object.keys(BData).forEach(key => {
+          if (/\$/.test(key)) return
+          _data[key.toLowerCase()] = BData[key]
+        })
+      }
+
       this.setState({
-        data: {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()},
+        data: _data
       })
       return
     } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -413,37 +435,14 @@
         }
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/card/cardItem/index.jsx b/src/tabviews/custom/components/card/cardItem/index.jsx
index aa25ec8..84b441d 100644
--- a/src/tabviews/custom/components/card/cardItem/index.jsx
+++ b/src/tabviews/custom/components/card/cardItem/index.jsx
@@ -53,18 +53,14 @@
         MenuID: menu.MenuID,
         MenuName: menu.MenuName,
         type: menu.tabType,
-        param: {}
+        param: {$BID: data.$$uuid || ''}
       }
 
-      if (card.setting.joint === 'true') {
-        newtab.param.$BID = data.$$uuid || ''
-
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          if (key === 'children') return
-          newtab.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        if (key === 'children') return
+        newtab.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', newtab, true)
     } else if (card.setting.click === 'menu') {
@@ -83,17 +79,13 @@
 
       if (!menu) return
 
-      menu.param = {}
-
-      if (card.setting.joint === 'true') {
-        menu.param.$BID = data.$$uuid || ''
+      menu.param = {$BID: data.$$uuid || ''}
         
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          if (key === 'children') return
-          menu.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        if (key === 'children') return
+        menu.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', menu, true)
     } else if (card.setting.click === 'link') {
@@ -107,6 +99,17 @@
         }
 
         src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
+      } else if (/@/.test(src)) {
+        src = src.replace(/@id@/ig, data.$$uuid || '')
+        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
+        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          let reg = new RegExp('@' + key + '@', 'ig')
+          src = src.replace(reg, data[key])
+        })
       }
 
       window.open(src)
@@ -114,7 +117,7 @@
       if (data.$$type === 'extendCard') {
         MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$selectedData || [])
       } else if (cards.subtype === 'datacard') {
-        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
+        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
       } else {
         MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
       }
@@ -132,7 +135,7 @@
       if (data.$$type === 'extendCard') {
         MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$selectedData || [])
       } else if (cards.subtype === 'datacard') {
-        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
+        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
       } else {
         MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
       }
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 7e16f86..d0eb21a 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -8,6 +8,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import { getMark } from '@/utils/utils.js'
 import MkIcon from '@/components/mk-icon'
+import MKEmitter from '@/utils/events.js'
 import Encrypts from '@/components/encrypts'
 import './index.scss'
 
@@ -24,7 +25,7 @@
 const FuncMegvii = asyncComponent(() => import('@/tabviews/zshare/actionList/funcMegvii'))
 const FuncZip = asyncComponent(() => import('@/tabviews/zshare/actionList/funczip'))
 const ExportPdf = asyncComponent(() => import('@/tabviews/zshare/actionList/exportPdf'))
-const ShareLink = asyncComponent(() => import('@/tabviews/zshare/actionList/shareLink'))
+const FuncButton = asyncComponent(() => import('@/tabviews/zshare/actionList/funcbutton'))
 const EditLine = asyncComponent(() => import('@/tabviews/zshare/actionList/editLine'))
 const BarCode = asyncComponent(() => import('@/components/barcode'))
 const QrCode = asyncComponent(() => import('@/components/qrcode'))
@@ -93,16 +94,40 @@
   openNewView = (e, card) => {
     const { cardCell, data, cards } = this.props
 
-    if (data.$disabled) return
+    e.stopPropagation()
 
-    if (card.anchors && card.anchors.length > 0) {
+    if (card.anchors) {
       let id = card.anchors[card.anchors.length - 1]
       let node = document.getElementById('anchor' + id)
       node && node.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'})
     }
 
-    if (!card.link || (card.linkType === 'qywx' || card.linkType === 'linkmenu')) return
-    e.stopPropagation()
+    if (card.linkType === 'qywx') return
+    if (card.linkType === 'linkmenu') {
+      if (card.linkThdMenu) {
+        let __param = {
+          $BID: data.$$uuid || ''
+        }
+  
+        if (card.field) {
+          __param.$searchkey = card.field.toLowerCase()
+          __param.$searchval = data[card.field] || ''
+        }
+      
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          if (key === 'children') return
+          __param[key] = data[key]
+        })
+
+        let tabmenu = card.linkThdMenu
+    
+        tabmenu.param = __param
+    
+        MKEmitter.emit('modifyTabs', tabmenu, true)
+      }
+      return
+    }
     
     let url = ''
 
@@ -209,15 +234,13 @@
       d.click()
       d.remove()
     } else {
+      let Id = data.$$uuid || ''
+
+      if (cards.subtype === 'propcard' && cardCell) {
+        Id = cardCell.setting.primaryId || ''
+      }
+
       if (card.joint === 'true') {
-        let Id = ''
-  
-        if (cards.subtype === 'propcard' && cardCell) {
-          Id = cardCell.setting.primaryId || ''
-        } else {
-          Id = data[cards.setting.primaryKey] || ''
-        }
-  
         let con = '?'
   
         if (/\?/ig.test(url)) {
@@ -225,6 +248,17 @@
         }
   
         url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
+      } else if (/@/.test(url)) {
+        url = url.replace(/@id@/ig, Id)
+        url = url.replace(/@appkey@/ig, window.GLOB.appkey)
+        url = url.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        url = url.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          let reg = new RegExp('@' + key + '@', 'ig')
+          url = url.replace(reg, data[key])
+        })
       }
   
       window.open(url)
@@ -433,7 +467,7 @@
           }
 
           if (card.copyable === 'true') {
-            if (card.link || (card.anchors && card.anchors.length > 0)) {
+            if (card.link || card.anchors) {
               let url = orival
 
               if (card.link === 'static') {
@@ -473,23 +507,31 @@
           }
           className = mark.signType
         }
-  
-        if (card.link || (card.anchors && card.anchors.length > 0)) {
-          _style.cursor = 'pointer'
-        }
     
         if (card.bgImage && data[card.bgImage]) {
           _style.backgroundImage = `url('${data[card.bgImage]}')`
         }
-  
-        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>}
+
+        if (!data.$disabled && (card.link || card.anchors)) {
+          _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 === 'number') {
         let val = ''
         let _style = {...card.style}
@@ -687,24 +729,31 @@
         _imagestyle.backgroundPosition = _style.backgroundPosition || 'center'
         _imagestyle.backgroundRepeat = _style.backgroundRepeat || 'no-repeat'
   
-        if (card.link) {
-          _style.cursor = 'pointer'
-        }
-
         if (_style.position === 'absolute') {
           _style.width = '100%'
         }
-  
+        
         let scale = url && card.scale === 'true'
         let urls = url ? url.split(',').filter(Boolean) : ['']
-
-        urls.forEach((u, i) => {
-          contents.push(<div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
-            <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
-              <MkPicture style={_imagestyle} lostTip={card.lostTip !== 'false'} scale={scale} url={u} urls={urls}/>
-            </div>
-          </div>)
-        })
+        
+        if (card.link && !data.$disabled) {
+          _style.cursor = 'pointer'
+          urls.forEach((u, i) => {
+            contents.push(<div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
+              <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
+                <MkPicture style={_imagestyle} lostTip={card.lostTip !== 'false'} scale={scale} url={u} urls={urls}/>
+              </div>
+            </div>)
+          })
+        } else {
+          urls.forEach((u, i) => {
+            contents.push(<div className={'ant-col ant-col-' + card.width} key={card.uuid + i} style={_style_} span={card.width}>
+              <div style={_style}>
+                <MkPicture style={_imagestyle} lostTip={card.lostTip !== 'false'} scale={scale} url={u} urls={urls}/>
+              </div>
+            </div>)
+          })
+        }
       } else if (card.eleType === 'splitline') {
         let _borderWidth = card.borderWidth === undefined ? 1 : card.borderWidth
         _style_ = _style_ || {}
@@ -821,14 +870,64 @@
             _data = [data]
           }
 
+          let _val = card.formula
+          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 || '')
+          }
+
           try {
             // eslint-disable-next-line
-            let func = new Function('data', card.formula)
+            let func = new Function('data', _val)
             val = func(_data)
           } catch (e) {
             console.warn(e)
             val = ''
           }
+
+          if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
+            return null
+          } else if (typeof(val) === 'object' && val.type === 'linkmenu') {
+            // type: 'linkmenu', linkThdMenu: null, menuId: '', value: ``, defaultValue: '', onclick: 'inner'
+            let item = {linkType: 'linkmenu', linkThdMenu: val.linkThdMenu}
+            let _val_ = val.value || ''
+
+            if (!item.linkThdMenu && val.menuId) {
+              item.linkThdMenu = window.GLOB.mkThdMenus.get(val.menuId) || ''
+            }
+            if (!item.linkThdMenu && val.defaultValue) {
+              _val_ = val.defaultValue
+            }
+
+            if (val.onclick === 'inner') {
+              contents.push(
+                <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+                  <div style={_style}>
+                    <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}}>
+                      <span onClick={(e) => {this.openNewView(e, item)}} dangerouslySetInnerHTML={{__html: _val_}}></span>
+                    </div>
+                  </div>
+                </div>
+              )
+            } else {
+              _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, item)}}>
+                    <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}} dangerouslySetInnerHTML={{__html: _val_}}></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}>
+                  <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}} dangerouslySetInnerHTML={{__html: val}}></div>
+                </div>
+              </div>
+            )
+          }
+          return
         } else if (card.$sync) {
           if (card.eval === 'false') {
             val = ''
@@ -858,6 +957,9 @@
           val = ''
         } else if (data) {
           let _val = card.formula
+          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 || '')
+          }
           Object.keys(data).forEach(key => {
             let reg = new RegExp('@' + key + '@', 'ig')
             _val = _val.replace(reg, data[key])
@@ -879,15 +981,6 @@
 
         if (!val && card.noValue === 'hide') { // 绌哄�奸殣钘�
           return null
-        } else if (card.eval === 'func') {
-          contents.push(
-            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
-              <div style={_style}>
-                <div className={'ant-mk-text line' + (card.height || '')} style={{height: card.innerHeight}} dangerouslySetInnerHTML={{__html: val}}></div>
-              </div>
-            </div>
-          )
-          return
         }
 
         if (card.round && typeof(val) === 'number') {
@@ -946,6 +1039,56 @@
             </div>
           </div>
         )
+      } else if (card.eleType === 'tag') {
+        let vals = ''
+  
+        if (card.datatype === 'static') {
+          vals = card.value
+        } else {
+          vals = data[card.field] || ''
+        }
+  
+        if (!vals && card.noValue === 'hide') { // 绌哄�奸殣钘�
+          return null
+        }
+
+        vals = vals.split(',').filter(Boolean)
+  
+        if (card.signs) {
+          vals = vals.map(val => {
+            let sign = card.signs.filter(s => s.value === val)[0]
+            let cell = {value: val, style: {...card.style}}
+
+            if (sign) {
+              cell.style.backgroundColor = sign.background
+              cell.style.color = sign.color
+              cell.style.borderColor = sign.border
+
+              // delete cell.style.borderTopColor
+              // delete cell.style.borderBottomColor
+              // delete cell.style.borderLeftColor
+              // delete cell.style.borderRightColor
+            }
+
+            return cell
+          })
+
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div className="ant-mk-tag">
+                {vals.map((item, index) => <span key={index} className="tag-item" style={item.style}>{item.value}</span>)}
+              </div>
+            </div>
+          )
+        } else {
+          contents.push(
+            <div className={'ant-col ant-col-' + card.width} key={card.uuid} style={_style_} span={card.width}>
+              <div className="ant-mk-tag">
+                {vals.map((val, index) => <span key={index} className="tag-item" style={card.style}>{val}</span>)}
+              </div>
+            </div>
+          )
+        }
       } else if (card.eleType === 'color') {
         let color = ''
   
@@ -1005,6 +1148,10 @@
         } else if (data.$$empty) {
           _data = []
         }
+        let name = ''
+        if (card.showName) {
+          name = data[card.showName] || ' '
+        }
 
         _style_ = _style_ || {}
         if (card.wrapStyle) {
@@ -1012,11 +1159,14 @@
         }
 
         let MkButton = null
+        let lid = (data.$$uuid || '') + (data.$Index || '')
   
         if (['exec', 'prompt', 'pop', 'form'].includes(card.OpenType)) {
           MkButton = <NormalButton
             btn={card}
+            name={name}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             setting={cards.setting}
@@ -1027,6 +1177,7 @@
           MkButton = <ExcelInButton
             btn={card}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             setting={cards.setting}
@@ -1036,6 +1187,7 @@
           MkButton = <ExcelOutButton
             btn={card}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             setting={cards.setting}
@@ -1044,7 +1196,9 @@
         } else if (card.OpenType === 'popview') {
           MkButton = <PopupButton
             btn={card}
+            name={name}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             setting={cards.setting}
@@ -1053,7 +1207,9 @@
         } else if (card.OpenType === 'tab') {
           MkButton = <TabButton
             btn={card}
+            name={name}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             selectedData={_data}
@@ -1061,7 +1217,9 @@
         } else if (card.OpenType === 'innerpage') {
           MkButton = <NewPageButton
             btn={card}
+            name={name}
             BID={data.$$BID}
+            LID={lid}
             BData={data.$$BData || ''}
             disabled={_disabled}
             selectedData={_data}
@@ -1071,6 +1229,7 @@
             MkButton = <ChangeUserButton
               btn={card}
               BID={data.$$BID}
+              LID={lid}
               BData={data.$$BData || ''}
               disabled={_disabled}
               setting={cards.setting}
@@ -1080,6 +1239,7 @@
             MkButton = <PrintButton
               btn={card}
               BID={data.$$BID}
+              LID={lid}
               BData={data.$$BData || ''}
               disabled={_disabled}
               setting={cards.setting}
@@ -1090,6 +1250,7 @@
             MkButton = <FuncMegvii
               btn={card}
               BID={data.$$BID}
+              LID={lid}
               disabled={_disabled}
               setting={cards.setting}
               selectedData={_data}
@@ -1098,6 +1259,7 @@
             MkButton = <FuncZip
               btn={card}
               BID={data.$$BID}
+              LID={lid}
               BData={data.$$BData || ''}
               disabled={_disabled}
               setting={cards.setting}
@@ -1106,12 +1268,7 @@
           } else if (card.funcType === 'expPdf') {
             MkButton = <ExportPdf
               btn={card}
-            />
-          } else if (card.funcType === 'shareLink') {
-            MkButton = <ShareLink
-              BID={data.$$BID}
-              btn={card}
-              selectedData={_data}
+              LID={lid}
             />
           } else if (card.funcType === 'addline' || card.funcType === 'delline') {
             MkButton = <EditLine
@@ -1119,6 +1276,14 @@
               disabled={_disabled}
               selectedData={_data}
             />
+          } else {
+            MkButton = <FuncButton
+              BID={data.$$BID}
+              disabled={_disabled}
+              LID={lid}
+              btn={card}
+              selectedData={_data}
+            />
           }
         }
 
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index fbd7791..e5cfb31 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -3,8 +3,24 @@
   position: relative;
   line-height: 1.5;
   
+  .ant-col-0:not(.mk-cell-btn) {
+    display: block;
+    float: left;
+  }
   .ant-btn {
     padding: 0;
+  }
+  .ant-btn.mk-btn-hover-bg:not([disabled]):hover {
+    opacity: 1!important;
+    color: #ffffff!important;
+    border-color: var(--mk-sys-color)!important;
+    background-color: var(--mk-sys-color)!important;
+  }
+  .ant-btn.mk-btn-hover-border:not([disabled]):hover {
+    opacity: 1!important;
+    color: var(--mk-sys-color)!important;
+    border-color: var(--mk-sys-color)!important;
+    background-color: #ffffff!important;
   }
   .file-image {
     max-height: 100%;
@@ -17,6 +33,7 @@
     font-style: inherit;
     font-weight: inherit;
     text-decoration: inherit;
+    font-family: inherit;
     color: inherit;
     .anticon-copy {
       color: var(--mk-sys-color);
@@ -26,6 +43,7 @@
     font-style: inherit;
     font-weight: inherit;
     text-decoration: inherit;
+    font-family: inherit;
     .sequence-wrap {
       display: inline-block;
       width: 21px;
@@ -41,6 +59,7 @@
       font-style: inherit;
       font-weight: inherit;
       text-decoration: inherit;
+      font-family: inherit;
     }
   }
   .ant-mk-text:not(.line1):not(.line) {
@@ -88,6 +107,7 @@
     background-size: cover;
   }
   .mk-cell-btn {
+    text-align: center;
     min-height: 0px;
     > div {width: 100%;max-width: 100%;}
     button:not(.ant-switch) {
@@ -97,6 +117,7 @@
       min-height: 28px;
       padding: 0;
       overflow: hidden;
+      text-align: inherit;
     }
     .ant-checkbox-wrapper:not(.square) {
       .ant-checkbox-inner, .ant-checkbox-checked::after {
@@ -154,6 +175,12 @@
     border-left: 0;
     border-right: 0;
   }
+  .ant-mk-tag {
+    .tag-item {
+      display: inline-block;
+      vertical-align: top;
+    }
+  }
   .ant-mk-check {
     white-space: nowrap;
     overflow: hidden;
diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx
index de3f1a8..1dca646 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, notification, message, Row, Col, Pagination, Modal, Switch } from 'antd'
+import { Spin, Empty, message, Row, Col, Pagination, Switch } from 'antd'
 import { DownOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -42,12 +42,11 @@
     precards: [],
     nextcards: [],
     selected: 'false',
-    supNodes: [],
-    supComs: null,
     pickup: false
   }
 
   loaded = false
+  supModules = []
 
   UNSAFE_componentWillMount () {
     const { config } = this.props
@@ -124,17 +123,12 @@
       _config.wrap.selected = 'false'
     }
 
-    let supComs = null
-    if (_config.wrap.supType === 'multi') {
-      supComs = _config.supNodes.map(item => item.componentId)
-    }
-
     _config.wrap.selStyle = _config.wrap.selStyle || 'active'
     _config.wrap.pagestyle = _config.wrap.pagestyle || 'page'
     _config.wrap.scale = _config.wrap.scale === 'true' ? 'scale' : ''
     _config.wrap.layout = (_config.wrap.layout || 'grid') + '-layout float-' + (_config.wrap.cardFloat || 'left')
 
-    _config.wrap.wrapClass = `${_config.wrap.selStyle} ${_config.wrap.cardType || ''} ${_config.wrap.scale}`
+    _config.wrap.wrapClass = `${_config.wrap.selStyle} ${_config.wrap.cardType || ''} ${_config.wrap.scale} ${config.wrap.hover === 'true' ? 'mk-hover' : ''}`
 
     if (_config.wrap.shifting === 'true') {
       _config.wrap.shifting = 'shifting'
@@ -197,7 +191,6 @@
     this.setState({
       pageSize: _config.setting.pageSize || 10,
       pageOptions,
-      supComs,
       selected,
       precards,
       nextcards,
@@ -412,14 +405,14 @@
    * @param {*} btn        // 鎵ц鐨勬寜閽�
    */
   refreshByButtonResult = (menuId, position, btn, id = '', lines) => {
-    const { config, BID, supComs, supNodes } = this.state
+    const { config, BID } = this.state
 
     if (config.uuid !== menuId) return
 
-    if (supComs) {
-      if (position === 'mainline' || position === 'popclose') { // 涓昏〃鍒锋柊锛屽幓闄ゅ悓姝ュ埛鏂扮粍浠�
-        let supNode = supNodes[supNodes.length - 1]
-        supComs.forEach((item, i) => {
+    if (config.supNodes) {
+      if (['mainline', 'maingrid', 'popclose'].includes(position)) {
+        let supNode = this.supModules[this.supModules.length - 1]
+        config.supNodes.forEach((item, i) => {
           setTimeout(() => {
             if (supNode && supNode.key === item) {
               MKEmitter.emit('reloadData', item, supNode.value)
@@ -454,8 +447,8 @@
         } else {
           this.loadData(id)
         }
-      } else if ((position === 'mainline' || position === 'popclose') && supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-        MKEmitter.emit('reloadData', supModule, BID)
+      } 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
@@ -678,28 +671,26 @@
   }
 
   resetParentParam = (MenuID, id, data) => {
-    const { config, supComs } = this.state
+    const { config } = this.state
 
-    if (supComs) {
-      if (!supComs.includes(MenuID)) return
-      let supNodes = this.state.supNodes.filter(item => item.key !== MenuID)
+    if (config.supNodes) {
+      if (!config.supNodes.includes(MenuID)) return
+      this.supModules = this.supModules.filter(item => item.key !== MenuID)
       let bid = ''
       let _data = null
 
       if (id) {
-        supNodes.push({key: MenuID, value: id, data})
+        this.supModules.push({key: MenuID, value: id, data})
       }
-      if (supNodes.length > 0) {
-        bid = supNodes[supNodes.length - 1].value
-        _data = supNodes[supNodes.length - 1].data
+      if (this.supModules.length > 0) {
+        bid = this.supModules[this.supModules.length - 1].value
+        _data = this.supModules[this.supModules.length - 1].data
       }
 
       if (bid !== this.state.BID || bid !== '') {
-        this.setState({ BID: bid, BData: _data, pageIndex: 1, supNodes }, () => {
+        this.setState({ BID: bid, BData: _data, pageIndex: 1 }, () => {
           this.loadData()
         })
-      } else {
-        this.setState({ supNodes })
       }
     } else {
       if (!config.setting.supModule || config.setting.supModule !== MenuID) return
@@ -755,13 +746,9 @@
         loading: false
       })
       
-      if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
-        this.prevCheck(id)
-      } else {
-        MKEmitter.emit('resetSelectLine', config.uuid, '', '')
-        if (config.setting.$hasSyncModule) {
-          MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-        }
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
+      if (config.setting.$hasSyncModule) {
+        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
       }
       return
     }
@@ -871,37 +858,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
 
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -1043,11 +1008,8 @@
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -1251,7 +1213,7 @@
               let className = 'mk-card '
               if (config.wrap.parity === 'true') {
                 if (index % 2 === 1) {
-                  className += 'mk-parity-bg '
+                  className += 'mk-even-line '
                 }
               }
               if (item.$disabled) {
diff --git a/src/tabviews/custom/components/card/data-card/index.scss b/src/tabviews/custom/components/card/data-card/index.scss
index b2def5d..e26e385 100644
--- a/src/tabviews/custom/components/card/data-card/index.scss
+++ b/src/tabviews/custom/components/card/data-card/index.scss
@@ -38,8 +38,15 @@
         }
       }
     }
-    .mk-parity-bg {
+    .mk-even-line {
       .card-item-box {
+        background-color: #fafafa;
+      }
+    }
+  }
+  .data-zoom.mk-hover {
+    .mk-card {
+      .card-item-box:hover {
         background-color: var(--mk-sys-color1);
       }
     }
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 4903092..4f56e58 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, notification, Row, Col, Pagination, Modal, Switch } from 'antd'
+import { Spin, Empty, Row, Col, Pagination, Switch } from 'antd'
 import { DownOutlined, UpOutlined, PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -372,8 +372,8 @@
       } else {
         this.loadData(id)
       }
-    } else if ((position === 'mainline' || position === 'popclose') && supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', supModule, BID)
+    } 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
@@ -595,17 +595,8 @@
         total: 0,
         loading: false
       })
-      
-      if (selected !== 'false' || (id && config.wrap.selected !== 'false')) {
-        setTimeout(() => {
-          this.checkTopLine(id)
-        }, 10)
-        if (selected === 'init') {
-          this.setState({selected: 'false'})
-        }
-      } else {
-        MKEmitter.emit('resetSelectLine', config.uuid, '', '')
-      }
+
+      MKEmitter.emit('resetSelectLine', config.uuid, '', '')
       return
     }
 
@@ -771,37 +762,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
 
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -959,11 +928,8 @@
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -1092,17 +1058,13 @@
 
     if (!menu) return
 
-    menu.param = {}
+    menu.param = {$BID: item.$$uuid || ''}
 
-    if (card.setting.joint === 'true') {
-      menu.param.$BID = item.$$uuid || ''
-      
-      Object.keys(item).forEach(key => {
-        if (/^\$/.test(key)) return
-        if (key === 'children') return
-        menu.param[key] = item[key]
-      })
-    }
+    Object.keys(item).forEach(key => {
+      if (/^\$/.test(key)) return
+      if (key === 'children') return
+      menu.param[key] = item[key]
+    })
 
     MKEmitter.emit('modifyTabs', menu, true)
   }
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 4d27218..3f19dd4 100644
--- a/src/tabviews/custom/components/card/double-data-card/index.scss
+++ b/src/tabviews/custom/components/card/double-data-card/index.scss
@@ -194,14 +194,14 @@
     >.card-row-list {
       >.ant-col:not(.extend-card) {
         .card-item-box:hover {
-          background-color: var(--mk-sys-color2);
+          background-color: var(--mk-sys-color1);
         }
       }
     }
     .sub-card-wrap.mk-parity-bg {
       .ant-col:nth-child(even){
         .card-item-box:not(:hover) {
-          background-color: var(--mk-sys-color1);
+          background-color: #fafafa;
         }
       }
     }
@@ -270,7 +270,7 @@
     .sub-card-wrap.mk-parity-bg {
       .ant-col:nth-child(even){
         .card-item-box {
-          background-color: var(--mk-sys-color1);
+          background-color: #fafafa;
         }
       }
     }
diff --git a/src/tabviews/custom/components/card/prop-card/index.jsx b/src/tabviews/custom/components/card/prop-card/index.jsx
index 1319e6d..cda84d4 100644
--- a/src/tabviews/custom/components/card/prop-card/index.jsx
+++ b/src/tabviews/custom/components/card/prop-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Col, Row, Modal } from 'antd'
+import { Spin, Col, Row } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -72,10 +72,26 @@
       this.loaded = true
     } else if (_config.wrap.datatype === 'static') {
       this.loaded = true
+      _config.subcards.forEach(card => {
+        card.elements.forEach(ele => {
+          if (ele.eleType === 'button') return
+          if (ele.datatype === 'dynamic' && ele.field) {
+            ele.field = ele.field.toLowerCase()
+          }
+        })
+      })
     }
 
     _data.$$BID = BID || ''
     _data.$$BData = BData || ''
+
+    if (_config.wrap.datatype === 'static' && BData) {
+      Object.keys(BData).forEach(key => {
+        if (/\$/.test(key)) return
+        _data[key.toLowerCase()] = BData[key]
+      })
+    }
+
     if (_config.setting.primaryKey) {
       _data.$$uuid = _data[_config.setting.primaryKey] || ''
     }
@@ -426,8 +442,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData('', btn)
     }
@@ -494,8 +510,16 @@
     }
     
     if (config.wrap.datatype === 'static') {
+      let _data = {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()}
+      if (BData) {
+        Object.keys(BData).forEach(key => {
+          if (/\$/.test(key)) return
+          _data[key.toLowerCase()] = BData[key]
+        })
+      }
+
       this.setState({
-        data: {$$BID: BID || '', $$BData: BData, $$empty: true, $$time: new Date().getTime()},
+        data: _data,
       })
 
       if (!btn) {
@@ -573,37 +597,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
 
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index 8dcb134..5251e62 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Row, Col, Empty, Pagination, Modal } from 'antd'
+import { Spin, Row, Col, Empty, Pagination } from 'antd'
 import { DownOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -12,6 +12,7 @@
 import './index.scss'
 
 const CardCellComponent = asyncComponent(() => import('../cardcellList'))
+const MainAction = asyncComponent(() => import('@/tabviews/zshare/actionList'))
 const NormalHeader = asyncComponent(() => import('@/tabviews/custom/components/share/normalheader'))
 
 class TableCard extends Component {
@@ -20,13 +21,14 @@
   }
 
   state = {
-    BID: '',                   // 涓婄骇ID
-    config: null,              // 鍥捐〃閰嶇疆淇℃伅
-    loading: false,            // 鏁版嵁鍔犺浇鐘舵��
-    search: null,              // 鎼滅储鏉′欢
-    pageIndex: 1,              // 椤电爜
-    total: 0,                  // 鎬绘暟
-    data: null,                // 鏁版嵁
+    BID: '',
+    config: null,
+    loading: false,
+    search: null,
+    pageIndex: 1,
+    total: 0,
+    data: null,
+    precards: [],
     BData: ''
   }
 
@@ -94,12 +96,22 @@
       }
     }
 
+    let precards = []
+    _config.subcards = _config.subcards.filter(item => {
+      if (item.setting.condition === 'title') {
+        precards.push(item)
+        return false
+      }
+      return true
+    })
+
     this.setState({
       BID: BID || '',
       BData: BData || '',
       data: _data,
       config: _config,
-      search: _config.$searches
+      search: _config.$searches,
+      precards
     })
   }
 
@@ -260,8 +272,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -417,37 +429,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -476,16 +466,12 @@
 
       if (!menu) return
 
-      menu.param = {}
+      menu.param = {$BID: data.$$uuid || ''}
 
-      if (card.setting.joint === 'true') {
-        menu.param.$BID = data.$$uuid || ''
-
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          menu.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        menu.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', menu, true)
     } else if (card.setting.click === 'link') {
@@ -499,21 +485,33 @@
         }
 
         src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
+      } else if (/@/.test(src)) {
+        src = src.replace(/@id@/ig, data.$$uuid || '')
+        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
+        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          let reg = new RegExp('@' + key + '@', 'ig')
+          src = src.replace(reg, data[key])
+        })
       }
 
       window.open(src)
     } else if (card.setting.click === 'button' && card.setting.linkbtn) {
-      MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
+      MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
     }
   }
 
-  getLines = (data) => {
+  getLines = (data, lindex) => {
     const { config } = this.state
 
     let line = []
 
     config.subcards.forEach((item, index) => {
       let display = item.setting.condition !== 'true'
+      let className = ''
 
       if (!display && item.setting.controlField) {
         let val = data[item.setting.controlField]
@@ -531,12 +529,20 @@
         } else if (item.setting.controlType === '<' && val < item.setting.controlValue) {
           display = true
         }
+
+        className = 'mk_line_' + val
       }
 
       if (!display) return
 
+      if (config.wrap.parity === 'true') {
+        if (lindex % 2 === 1) {
+          className += ' mk-even-line'
+        }
+      }
+
       line.push(
-        <Col key={index} span={24}>
+        <Col key={index} className={className} span={24}>
           <div className="card-item-box" style={item.style} onClick={() => {this.openView(item, data)}}>
             <CardCellComponent data={data} cards={config} cardCell={item} elements={item.elements}/>
           </div>
@@ -571,7 +577,7 @@
   }
 
   render() {
-    const { config, loading, data, BID, pageIndex, total } = this.state
+    const { config, loading, data, BID, pageIndex, total, BData, precards } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.length === 0)) return null
     
@@ -584,12 +590,27 @@
           </div> : null
         }
         <NormalHeader config={config} BID={BID} refresh={this.refreshSearch} />
-        {data && data.length > 0 ? <Row className={'card-row-list' + (config.wrap.parity === 'true' ? ' mk-parity' : '')} style={{height: config.wrap.contentHeight}}>
-          {data.map(item => this.getLines(item))}
-        </Row> : null}
-        {data && data.length === 0 ? <div className="card-row-list" style={{height: config.wrap.contentHeight}}>
-          <Empty description={false}/>
-        </div> : null}
+        {config.action && config.action.length > 0 ?
+          <MainAction
+            BID={BID}
+            BData={BData}
+            setting={config.setting}
+            actions={config.action}
+            columns={config.columns}
+            selectedData={[]}
+          /> : null
+        }
+        <Row className={`card-row-list ${config.wrap.hover === 'true' ? 'mk-hover' : ''}`} style={{height: config.wrap.contentHeight}}>
+          {precards.map((item, index) => (
+            <Col key={index} className="extend-card" span={24}>
+              <div className="card-item-box" style={item.style}>
+                <CardCellComponent data={data && data[0] ? data[0] : {}} cards={config} cardCell={item} elements={item.elements}/>
+              </div>
+            </Col>
+          ))}
+          {data && data.length > 0 ? data.map((item, index) => this.getLines(item, index)) : null}
+          {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}
       </div>
diff --git a/src/tabviews/custom/components/card/table-card/index.scss b/src/tabviews/custom/components/card/table-card/index.scss
index 088083a..10fb9be 100644
--- a/src/tabviews/custom/components/card/table-card/index.scss
+++ b/src/tabviews/custom/components/card/table-card/index.scss
@@ -33,13 +33,6 @@
     clear: both;
   }
 
-  .mk-parity {
-    >.ant-col:nth-child(even) {
-      .card-item-box {
-        background-color: var(--mk-sys-color1);
-      }
-    }
-  }
   .card-row-list {
     overflow-y: auto;
     .card-item-box {
@@ -47,9 +40,17 @@
       background-color: #ffffff;
       transition: all 0.3s;
     }
-    >.active >.card-item-box {
-      border-color: #1890ff!important;
-      box-shadow: 0 0 3px #1890ff;
+    .mk-even-line {
+      .card-item-box {
+        background-color: #fafafa;
+      }
+    }
+  }
+  .card-row-list.mk-hover {
+    >.ant-col:not(.extend-card) {
+      .card-item-box:hover {
+        background-color: var(--mk-sys-color1);
+      }
     }
   }
   .card-row-list::-webkit-scrollbar {
diff --git a/src/tabviews/custom/components/carousel/cardItem/index.jsx b/src/tabviews/custom/components/carousel/cardItem/index.jsx
index 1ed6197..9b0d0d8 100644
--- a/src/tabviews/custom/components/carousel/cardItem/index.jsx
+++ b/src/tabviews/custom/components/carousel/cardItem/index.jsx
@@ -57,16 +57,12 @@
 
       if (!menu) return
 
-      menu.param = {}
+      menu.param = {$BID: data.$$uuid || ''}
 
-      if (card.setting.joint === 'true') {
-        menu.param.$BID = data.$$uuid || ''
-
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          menu.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        menu.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', menu, true)
     } else if (card.setting.click === 'link') {
@@ -80,12 +76,23 @@
         }
 
         src = src + `${con}id=${data.$$uuid || ''}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
+      } else if (/@/.test(src)) {
+        src = src.replace(/@id@/ig, data.$$uuid || '')
+        src = src.replace(/@appkey@/ig, window.GLOB.appkey)
+        src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          let reg = new RegExp('@' + key + '@', 'ig')
+          src = src.replace(reg, data[key])
+        })
       }
 
       window.open(src)
     } else if (card.setting.click === 'button' && card.setting.linkbtn) {
       if (cards.subtype === 'datacard') {
-        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn')
+        MKEmitter.emit('triggerBtnId', card.setting.linkbtn, [data], 'linkbtn', (data.$$uuid || '') + (data.$Index || ''))
       } else {
         MKEmitter.emit('triggerBtnId', card.setting.linkbtn, data.$$empty ? [] : [data])
       }
diff --git a/src/tabviews/custom/components/carousel/data-card/index.jsx b/src/tabviews/custom/components/carousel/data-card/index.jsx
index 45a3656..64f8dc1 100644
--- a/src/tabviews/custom/components/carousel/data-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/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, notification, Carousel, Modal, Checkbox, Button } from 'antd'
+import { Spin, Empty, Carousel, Modal, Checkbox, Button } from 'antd'
 import { LeftOutlined, RightOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -282,8 +282,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -379,37 +379,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/carousel/prop-card/index.jsx b/src/tabviews/custom/components/carousel/prop-card/index.jsx
index 572b869..efa162d 100644
--- a/src/tabviews/custom/components/carousel/prop-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Carousel, Modal, Checkbox, Button } from 'antd'
+import { Spin, Carousel, Modal, Checkbox, Button } from 'antd'
 import { LeftOutlined, RightOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -66,11 +66,27 @@
 
         window.GLOB.SyncData.delete(_config.dataName)
       }
+    } else {
+      _config.subcards.forEach(card => {
+        card.elements.forEach(ele => {
+          if (ele.eleType === 'button') return
+          if (ele.datatype === 'dynamic' && ele.field) {
+            ele.field = ele.field.toLowerCase()
+          }
+        })
+      })
     }
 
     _data.$$uuid = _data[_config.setting.primaryKey] || ''
     _data.$$BID = BID || ''
     _data.$$BData = BData || ''
+
+    if (_config.wrap.datatype === 'static' && BData) {
+      Object.keys(BData).forEach(key => {
+        if (/\$/.test(key)) return
+        _data[key.toLowerCase()] = BData[key]
+      })
+    }
 
     if (!_config.wrap.height) { // 鍏煎
       _config.wrap.height = _config.style.height || '300px'
@@ -270,8 +286,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -319,8 +335,16 @@
     const { config, BID, BData } = this.state
 
     if (config.wrap.datatype === 'static') {
+      let _data = {$$BID: BID || '', $$BData: BData, $$empty: true}
+      if (BData) {
+        Object.keys(BData).forEach(key => {
+          if (/\$/.test(key)) return
+          _data[key.toLowerCase()] = BData[key]
+        })
+      }
+
       this.setState({
-        data: {$$BID: BID || '', $$BData: BData, $$empty: true}
+        data: _data
       })
       return
     } else if (config.setting.supModule && !BID) { // BID 涓嶅瓨鍦ㄦ椂锛屼笉鍋氭煡璇�
@@ -382,37 +406,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/chart/antv-G6/index.jsx b/src/tabviews/custom/components/chart/antv-G6/index.jsx
index 64536d5..fef955f 100644
--- a/src/tabviews/custom/components/chart/antv-G6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-G6/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Modal, notification, Spin, Empty } from 'antd'
+import { Spin, Empty } from 'antd'
 import G6 from '@antv/g6'
 
 import Api from '@/api'
@@ -1167,36 +1167,14 @@
         this.data = result.data || []
         this.handleData()
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -1643,17 +1621,13 @@
         MenuName: menu.MenuName,
         MenuNo: menu.MenuNo || '',
         type: menu.tabType,
-        param: {}
+        param: {$BID: data.$$uuid || ''}
       }
 
-      if (plot.joint === 'true') {
-        newtab.param.$BID = data.$$uuid || ''
-
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          newtab.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        newtab.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', newtab, true)
     } else if (plot.click === 'menu') {
@@ -1674,16 +1648,12 @@
 
       if (!menu) return
 
-      menu.param = {}
+      menu.param = {$BID: data.$$uuid || ''}
 
-      if (plot.joint === 'true') {
-        menu.param.$BID = data.$$uuid || ''
-
-        Object.keys(data).forEach(key => {
-          if (/^\$/.test(key)) return
-          menu.param[key] = data[key]
-        })
-      }
+      Object.keys(data).forEach(key => {
+        if (/^\$/.test(key)) return
+        menu.param[key] = data[key]
+      })
 
       MKEmitter.emit('modifyTabs', menu, true)
     } else {
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.jsx b/src/tabviews/custom/components/chart/antv-X6/index.jsx
index faedfd9..ad2f38a 100644
--- a/src/tabviews/custom/components/chart/antv-X6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/index.jsx
@@ -1,8 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, Tooltip, message, Modal, notification, Switch } from 'antd'
-import { UndoOutlined, RedoOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, QuestionCircleOutlined, ClearOutlined } from '@ant-design/icons'
+import { Spin, Tooltip, message, Modal, notification, Switch, Button } from 'antd'
+import { UndoOutlined, RedoOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, QuestionCircleOutlined, ClearOutlined } from '@ant-design/icons'
 import { Graph, Shape } from '@antv/x6'
 import { Stencil } from '@antv/x6-plugin-stencil'
 import { Transform } from '@antv/x6-plugin-transform'
@@ -388,7 +388,8 @@
     status: 0,
     flowname: '',
     flowcode: '',
-    orgs: []
+    orgs: [],
+    empty: true
   }
 
   selectNode = null
@@ -526,6 +527,7 @@
                     worker_id: work.worker_id || '',
                     workercode: work.workercode || '',
                     workername: work.workername || '',
+                    job_type: job.job_type || '',
                     parentIds: [com.OrgCode, dep.co_pro_code, job.jobcode],
                     parentNames: [com.OrgName, dep.co_pro_name, job.jobname]
                   }
@@ -553,6 +555,7 @@
                     worker_id: work.worker_id || '',
                     workercode: work.workercode || '',
                     workername: work.workername || '',
+                    job_type: job.job_type || '',
                     parentIds: [com.OrgCode, dep.co_pro_code, job.jobcode, group.work_group],
                     parentNames: [com.OrgName, dep.co_pro_name, job.jobname, group.work_group]
                   }
@@ -590,8 +593,8 @@
     const { BID } = this.state
 
     if (!BID) {
+      this.cells = []
       if (!is(fromJS(this.data), fromJS([]))) {
-        this.cells = []
         this.handleData()
       }
       this.setState({empty: true})
@@ -624,7 +627,8 @@
         status: item.status || 0,
         flowname: item.works_flow_name || '',
         flowcode: item.works_flow_code || '',
-        loading: false
+        loading: false,
+        empty: cells.length === 0
       })
 
       if (result.message) {
@@ -994,6 +998,18 @@
 
       graph.clearTransformWidgets()
     })
+
+    graph.on('node:dblclick', () => {
+      setTimeout(() => {
+        MKEmitter.emit('mk-x6-dbclick')
+      }, 100)
+    })
+    graph.on('edge:dblclick', () => {
+      setTimeout(() => {
+        MKEmitter.emit('mk-x6-dbclick')
+      }, 100)
+    })
+
     graph.on('blank:click', () => {
       this.selectNode = null
       
@@ -1003,15 +1019,30 @@
       if (!isNew) return
 
       let target = edge.getTargetCell()
+      let source = edge.getSourceCell()
 
-      if (!target) return
+      if (!target || !source) return
+
+      if (source.prop('mknode') === 'end') {
+        notification.warning({
+          top: 92,
+          message: '缁撴潫鑺傜偣涓嶅彲娣诲姞鍒嗘敮锛�',
+          duration: 2
+        })
+        graph.removeCells([edge])
+        return
+      }
 
       let mkdata = target.prop('mkdata')
 
-      if (target.prop('mknode') === 'end') {
+      if (source.prop('mknode') === 'start' && target.prop('mknode') === 'end') {
+        edge.prop('mknode', 'throughEdge')
+      } else if (target.prop('mknode') === 'end') {
         edge.prop('mknode', 'endEdge')
       } else if (target.prop('mknode') === 'start') {
         edge.prop('mknode', 'startEdge')
+      } else if (source.prop('mknode') === 'start') {
+        edge.prop('mknode', 'firstEdge')
       }
       if (mkdata) {
         edge.prop('mkdata', {status: mkdata.status, statusName: mkdata.statusName})
@@ -1544,6 +1575,26 @@
     this.mkGraph.zoomTo(1)
   }
 
+  close = () => {
+    const { config } = this.state
+
+    let nodes = this.mkGraph.toJSON()
+
+    if (!is(fromJS(nodes.cells), fromJS(this.cells))) {
+      confirm({
+        title: '娴佺▼鍥惧凡淇敼锛岀‘瀹氬叧闂悧?',
+        okText: '纭畾',
+        cancelText: '鍙栨秷',
+        onOk() {
+          MKEmitter.emit('closeTabView', config.$pageId)
+        },
+        onCancel() {}
+      })
+    } else {
+      MKEmitter.emit('closeTabView', config.$pageId)
+    }
+  }
+
   save = () => {
     const { BID, plot, status, flowname, flowcode } = this.state
 
@@ -1574,7 +1625,13 @@
         } else if (item.mknode === 'end') {
           end_num++
         } else if (item.shape === 'edge') {
-          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
+          if (item.mknode === 'throughEdge') {
+            if (!item.mkdata.seniorbers || item.mkdata.seniorbers.length === 0) {
+              unvalid = true
+            }
+          } else if (item.mkdata.seniorCondition === 'open') {
+
+          } else if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
             unvalid = true
           } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
             if (map.has(item.source.cell)) {
@@ -1596,7 +1653,7 @@
         }
       })
 
-      if (start_num !== 1 || end_num !== 1 || unvalid) {
+      if (start_num !== 1 || end_num === 0 || unvalid) {
         _status = 0
       }
     }
@@ -1638,6 +1695,7 @@
                   loading: false,
                   status: _status
                 })
+                this.cells = nodes.cells
               } else {
                 notification.error({
                   top: 92,
@@ -1659,6 +1717,7 @@
               loading: false,
               status: _status
             })
+            this.cells = nodes.cells
           }
         } else {
           notification.error({
@@ -1833,6 +1892,16 @@
         cell.prop('position/y', y1)
       }
     }
+  }
+
+  delCell = () => {
+    const { node } = this.state
+
+    let cell = this.mkGraph.getCellById(node.id)
+
+    this.mkGraph.removeCells([cell])
+
+    this.setState({node: null})
   }
 
   changeProps = (value, key) => {
@@ -2040,7 +2109,13 @@
         } else if (item.mknode === 'end') {
           end_num++
         } else if (item.shape === 'edge' && !unvalidId && !rejectId && !approvalId) {
-          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
+          if (item.mknode === 'throughEdge') {
+            if (!item.mkdata.seniorbers || item.mkdata.seniorbers.length === 0) {
+              unvalidId = item.id
+            }
+          } else if (item.mkdata.seniorCondition === 'open') {
+
+          } else if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
             unvalidId = item.id
           } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
             if (map.has(item.source.cell)) {
@@ -2080,12 +2155,12 @@
           message: '璇锋坊鍔犵粨鏉熻妭鐐癸紒',
           duration: 2
         })
-      } else if (end_num > 1) {
-        notification.warning({
-          top: 92,
-          message: '缁撴潫鑺傜偣涓嶅彲娣诲姞澶氫釜锛�',
-          duration: 2
-        })
+      // } else if (end_num > 1) {
+      //   notification.warning({
+      //     top: 92,
+      //     message: '缁撴潫鑺傜偣涓嶅彲娣诲姞澶氫釜锛�',
+      //     duration: 2
+      //   })
       } else if (emptyNode) {
         let errmsg = '閮ㄥ垎鑺傜偣鏈缃熀鏈俊鎭��'
         if (emptyNode.attrs && emptyNode.attrs.text && emptyNode.attrs.text.text) {
@@ -2202,12 +2277,12 @@
   }
 
   render() {
-    const { loading, config, node, orgs, status, flowname } = this.state
+    const { loading, config, node, orgs, status, flowname, empty } = this.state
 
     let style = {...config.style}
 
     if (config.plot.function === 'show') {
-      if (config.plot.empty === 'hidden' && this.cells.length === 0) {
+      if (config.plot.empty === 'hidden' && empty) {
         style.position = 'absolute'
         style.width = '100%'
         style.zIndex = -1
@@ -2264,18 +2339,15 @@
             <Tooltip title="娓呯┖">
               <ClearOutlined onClick={this.clearNode}/>
             </Tooltip>
-            <Tooltip overlayStyle={{maxWidth: 260}} title="蹇嵎閿細澶嶅埗锛坈trl+c锛夈�佸壀鍒囷紙ctrl+x锛夈�佺矘璐达紙ctrl+v锛夈�佸悗閫�锛坈trl+z锛夈�佸墠杩涳紙ctrl+shift+z锛夈�佸垹闄わ紙backspace 鎴� delete锛�">
+            <Tooltip overlayStyle={{maxWidth: 310}} title="蹇嵎閿細澶嶅埗锛坈trl+c锛夈�佸壀鍒囷紙ctrl+x锛夈�佺矘璐达紙ctrl+v锛夈�佸悗閫�锛坈trl+z锛夈�佸墠杩涳紙ctrl+shift+z锛夈�佸垹闄わ紙backspace 鎴� delete锛夛紱鍙屽嚮鑺傜偣鎴栬繛绾垮彲缂栬緫鑷畾涔変俊鎭��">
               <QuestionCircleOutlined />
             </Tooltip>
           </div>
           <div className="flow-name">{flowname}</div>
           <div className="right-tool">
-            <Tooltip title="鍚敤/鍋滅敤">
-              <Switch size="small" style={{marginRight: '10px'}} checked={status === 10} onChange={this.changeStatus} />
-            </Tooltip>
-            <Tooltip title="淇濆瓨">
-              <SaveOutlined style={{marginRight: '10px'}} onClick={this.save}/>
-            </Tooltip>
+            <Switch size="large" checked={status === 10} checkedChildren="鍚�" unCheckedChildren="鍋�" onChange={this.changeStatus} />
+            <Button className="save" onClick={this.save}>淇濆瓨</Button>
+            <Button className="close" onClick={this.close}>鍏抽棴</Button>
           </div>
         </div>
         <div className="canvas" style={{width: '100%', minHeight: config.plot.height, height: config.plot.height}} id={config.uuid + 'canvas'}>
@@ -2283,7 +2355,7 @@
           <div id={config.uuid + 'container'} className="mk-container"></div>
           <div className="mk-node-edit">
             <div className="header">璁剧疆</div>
-            {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} orgs={orgs} onChange={this.changeProps}/>}
+            {!node ? <div className="empty">鏈�変腑</div> : <NodeUpdate node={node} orgs={orgs} onChange={this.changeProps} onDel={this.delCell}/>}
           </div>
         </div>
       </div>
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.scss b/src/tabviews/custom/components/chart/antv-X6/index.scss
index ccaccfb..5fc7c62 100644
--- a/src/tabviews/custom/components/chart/antv-X6/index.scss
+++ b/src/tabviews/custom/components/chart/antv-X6/index.scss
@@ -32,10 +32,34 @@
     .right-tool {
       float: right;
       line-height: 40px;
-      .anticon {
-        margin: 0 10px;
-        font-size: 16px;
-        cursor: pointer;
+
+      .ant-switch {
+        min-width: 60px;
+        height: 28px;
+        line-height: 28px;
+        margin-top: -2px;
+        .ant-switch-inner {
+          font-size: 14px;
+        }
+      }
+      .ant-switch:after {
+        width: 24px;
+        height: 24px;
+      }
+      .save, .save:hover, .save:active, .save:focus {
+        border-color: var(--mk-sys-color);
+        background-color: var(--mk-sys-color);
+        color: #ffffff;
+        margin: 0 15px;
+        height: 30px;
+      }
+      .close {
+        margin-right: 15px;
+      }
+      .close:hover, .close:active, .close:focus {
+        border-color: var(--mk-sys-color);
+        color: var(--mk-sys-color);
+        height: 30px;
       }
     }
   }
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
index 9ff4eb4..3c0f69a 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
@@ -2,10 +2,11 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Form, Row, Col, Input, Select, Radio, InputNumber, Modal } from 'antd'
-import { FormOutlined } from '@ant-design/icons'
+import { FormOutlined, DeleteOutlined } from '@ant-design/icons'
 
 import ColorSketch from '@/tabviews/zshare/mutilform/mkColor'
 import NodeForm from './nodeform'
+import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 const { TextArea } = Input
@@ -30,6 +31,10 @@
     })
   }
 
+  componentDidMount () {
+    MKEmitter.addListener('mk-x6-dbclick', this.trigger)
+  }
+
   UNSAFE_componentWillReceiveProps(nextProps) {
     if (!is(fromJS(this.props.node), fromJS(nextProps.node))) {
       this.setState({
@@ -42,6 +47,25 @@
         })
       })
     }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+
+    MKEmitter.removeListener('mk-x6-dbclick', this.trigger)
+  }
+
+  trigger = () => {
+    const { formlist } = this.state
+
+    if (!formlist || formlist.findIndex(item => item.type === 'other') === -1) return
+
+    this.setState({visible: true})
   }
 
   getFormList = (node) => {
@@ -470,12 +494,13 @@
       } else if (item.type === 'other') {
         fields.push(
           <Col span={24} key={index}>
-            <span className="split-line">{item.label}锛�<FormOutlined onClick={() => {this.setState({visible: true})}}/></span>
+            <span className="split-line">{item.label}:<FormOutlined onClick={() => {this.setState({visible: true})}}/><DeleteOutlined onClick={() => this.props.onDel()}/></span>
             {mkdata ? <div className="mk-data">
               <div>鐘舵�侊細{mkdata.status}<span style={{float: 'right'}}>{mkdata.statusName}</span></div>
               {mknode.shape !== 'edge' && !mknode.mknode ? <div>鏍囪锛歿mkdata.sign || ''}</div> : null}
               {mknode.shape === 'edge' && mkdata.flowType ? <div>鎿嶄綔锛歿mkdata.flowType === 'reject' ? '椹冲洖' : '瀹℃壒'}</div> : null}
               {mkdata.members && mkdata.members.length ? <div>瀹℃壒浜猴細{mkdata.members.map(item => item.workername).join('銆�')}</div> : null}
+              {mkdata.seniorbers && mkdata.seniorbers.length ? <div>鐗规畩瀹℃壒浜猴細{mkdata.seniorbers.map(item => item.workername).join('銆�')}</div> : null}
               {mkdata.copys && mkdata.copys.length ? <div>鎶勯�佷汉锛歿mkdata.copys.map(item => item.workername).join('銆�')}</div> : null}
               <div>澶囨敞锛歿mkdata.remark || ''}</div>
             </div> : null}
@@ -496,10 +521,12 @@
         </Form>
         <Modal
           title={mknode && mknode.shape === 'edge' ? '杩炵嚎缂栬緫' : '鑺傜偣缂栬緫'}
+          wrapClassName="mk-x6-modal"
           visible={visible}
           closable={false}
           maskClosable={false}
-          width={1050}
+          width={1070}
+          centered={true}
           onOk={this.confirm}
           onCancel={() => this.setState({visible: false})}
           destroyOnClose
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
index a161a64..1c59391 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -7,6 +7,16 @@
     margin: 5px 12px 10px;
     padding-bottom: 2px;
     font-size: 13px;
+
+    >.anticon-delete {
+      padding: 0 5px;
+      float: right;
+      color: #f5222d;
+      line-height: 22px;
+    }
+    >.anticon-form {
+      padding: 0 5px;
+    }
   }
   .mk-data {
     font-size: 13px;
@@ -110,6 +120,7 @@
 }
 
 .normal-node-form {
+  padding: 0 24px;
   >.ant-row >.ant-col-24 {
     .ant-form-item-label {
       width: 16%;
@@ -118,8 +129,15 @@
       width: 84%;
     }
   }
+  .mk-split {
+    color: var(--mk-sys-color);
+    border-bottom: 1px solid #e8e8e8;
+    padding-left: 15px;
+    padding-bottom: 5px;
+  }
   .member-input {
     display: inline-block;
+    cursor: pointer;
     width: 100%;
     height: 32px;
     padding: 4px 11px;
@@ -179,7 +197,26 @@
     }
   }
 }
-
+.mk-x6-modal {
+  .ant-modal-body {
+    max-height: calc(100vh - 170px);
+    overflow-y: auto;
+  }
+  .ant-modal-body::-webkit-scrollbar {
+    width: 7px;
+  }
+  .ant-modal-body::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .ant-modal-body::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
+}
 .member-modal {
   .ant-modal {
     top: 50px;
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
index 0d89461..1304c3d 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
@@ -175,7 +175,7 @@
 
     return (
       <>
-        <div className="member-input">{value.length > 0 ? value.length + '浜�' : ''}<FormOutlined onClick={this.trigger} /></div>
+        <div className="member-input" onClick={this.trigger}>{value.length > 0 ? value.length + '浜�' : ''}<FormOutlined /></div>
         <Modal
           wrapClassName="member-modal"
           title="閫夋嫨浜哄憳"
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
index a400204..c9e04e2 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Tooltip, InputNumber, Switch } from 'antd'
+import { Form, Row, Col, Input, Radio, Tooltip, InputNumber, Switch, notification } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import MemberForm from './memberform'
@@ -10,18 +10,82 @@
   static propTpyes = {
     node: PropTypes.any,
     data: PropTypes.any,
-    orgs: PropTypes.array
+    orgs: PropTypes.array,
+    handleSubmit: PropTypes.func
   }
 
   state = {
-    flowType: this.props.data.flowType || 'approval',
-    execCondition: this.props.data.execCondition === 'open',
+    flowType: 'approval',
+    execCondition: false,
+    seniorCondition: false,
+    approvalMethod: 'orsign',
+    readOnly: false,
+    options: []
+  }
+
+  UNSAFE_componentWillMount() {
+    const { node, data } = this.props
+
+    let options = []
+    let readOnly = false
+
+    if (node.mknode === 'start') {
+      readOnly = true
+    } else if (node.mknode === 'end') {
+
+    } else if (node.mknode === 'throughEdge') {
+      options = ['senior']
+    } else if (node.mknode === 'endEdge') {
+      options = ['approvalMethod', 'execCondition']
+    } else if (node.mknode === 'startEdge') {
+      readOnly = true
+    } else if (node.mknode === 'firstEdge') {
+      options = ['approver', 'members', 'copys']
+    } else if (node.shape !== 'edge') { // node
+      options = ['sign']
+    } else {
+      options = ['flowType', 'approvalMethod', 'approver', 'members', 'copys', 'execCondition', 'senior']
+    }
+
+    this.setState({
+      flowType: data.flowType || 'approval',
+      execCondition: options.includes('execCondition') ? data.execCondition === 'open' : false,
+      seniorCondition: options.includes('senior') ? data.seniorCondition === 'open' : false,
+      approvalMethod: data.approvalMethod || 'orsign',
+      options,
+      readOnly
+    })
   }
 
   handleConfirm = () => {
+    const { node } = this.props
+
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
+
+          if (values.approvalMethod === 'countersign' && values.members.length > 5) {
+            notification.warning({
+              top: 92,
+              message: '浼氱鏃跺鎵逛汉涓嶅彲瓒呰繃5浜猴紒',
+              duration: 10
+            })
+            return
+          } else if (node.mknode === 'throughEdge' && values.seniorCondition === false) {
+            notification.warning({
+              top: 92,
+              message: '寮�濮嬩笌缁撴潫鐩磋繛鐨勫垎鏀繀椤昏缃壒娈婂鎵逛汉锛�',
+              duration: 10
+            })
+            return
+          }
+
+          if (values.seniorCondition === true) {
+            values.seniorCondition = 'open'
+          } else if (values.seniorCondition === false) {
+            values.seniorCondition = 'close'
+          }
+
           if (values.execCondition === true) {
             values.execCondition = 'open'
           } else if (values.execCondition === false) {
@@ -40,9 +104,9 @@
   }
 
   render() {
-    const { node, orgs } = this.props
+    const { orgs } = this.props
     const { getFieldDecorator } = this.props.form
-    const { flowType, execCondition } = this.state
+    const { flowType, execCondition, seniorCondition, approvalMethod, readOnly, options } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -54,32 +118,22 @@
       }
     }
     let data = this.props.data || {}
-    let nodetype = node.shape !== 'edge' ? 'node' : 'edge'
-    if (node.mknode === 'start') {
-      nodetype = 'start'
-    } else if (node.mknode === 'end') {
-      nodetype = 'end'
-    } else if (node.mknode === 'endEdge') {
-      nodetype = 'endEdge'
-    } else if (node.mknode === 'startEdge') {
-      nodetype = 'startEdge'
-    }
 
     return (
       <Form {...formItemLayout} className="normal-node-form">
         <Row gutter={24}>
+          {options.includes('approver') || options.includes('execCondition') ? <Col span={24}>
+            <p className="mk-split">鎸夐挳鎵ц鍛戒护</p>
+          </Col> : null}
           <Col span={12}>
             <Form.Item label="鐘舵�佸��">
               {getFieldDecorator('status', {
                 initialValue: data.status,
                 rules: [
-                  {
-                    required: true,
-                    message: '璇疯緭鍏ョ姸鎬佸��!'
-                  }
+                  { required: true, message: '璇疯緭鍏ョ姸鎬佸��!' }
                 ]
               })(
-                <InputNumber readOnly={nodetype !== 'node' && nodetype !== 'edge'} precision={0}/>
+                <InputNumber readOnly={readOnly} precision={0} onPressEnter={() => this.props.handleSubmit()}/>
               )}
             </Form.Item>
           </Col>
@@ -88,11 +142,11 @@
               {getFieldDecorator('statusName', {
                 initialValue: data.statusName || ''
               })(
-                <Input placeholder="" autoComplete="off"/>
+                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
               )}
             </Form.Item>
           </Col>
-          {nodetype === 'node' ? <Col span={12}>
+          {options.includes('sign') ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鏍囪灏嗕綔涓鸿妭鐐笽D">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -102,11 +156,11 @@
               {getFieldDecorator('sign', {
                 initialValue: data.sign || ''
               })(
-                <Input placeholder="" autoComplete="off"/>
+                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' ? <Col span={12}>
+          {options.includes('flowType') ? <Col span={12}>
             <Form.Item label="鎿嶄綔绫诲瀷">
               {getFieldDecorator('flowType', {
                 initialValue: flowType
@@ -118,7 +172,48 @@
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' ? <Col span={12}>
+          {options.includes('approvalMethod') && flowType !== 'reject' ? <Col span={12}>
+            <Form.Item label="瀹℃壒鏂瑰紡">
+              {getFieldDecorator('approvalMethod', {
+                initialValue: approvalMethod
+              })(
+                <Radio.Group onChange={(e) => this.setState({approvalMethod: e.target.value})}>
+                  <Radio value="orsign">鎴栫</Radio>
+                  <Radio value="countersign">浼氱</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {options.includes('approvalMethod') && flowType !== 'reject' && approvalMethod === 'countersign' ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="绀轰緥锛氣�滆储鍔$粡鐞嗗紶鎬诲凡瀹℃牳鈥濓紝鍏朵腑鈥滃凡瀹℃牳鈥濅负浼氱鏍囪銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                浼氱鏍囪
+              </Tooltip>
+            }>
+              {getFieldDecorator('mark', {
+                initialValue: data.mark || '宸插鏍�',
+                rules: [
+                  { required: true, message: '璇疯緭鍏ヤ細绛炬爣璁�!' }
+                ]
+              })(
+                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={24}>
+            <Form.Item label="澶囨敞">
+              {getFieldDecorator('remark', {
+                initialValue: data.remark || ''
+              })(
+                <TextArea rows={2}/>
+              )}
+            </Form.Item>
+          </Col>
+          {options.includes('approver') ? <Col span={24}>
+            <p className="mk-split">涓嬩竴姝ュ鎵规潈闄�</p>
+          </Col> : null}
+          {options.includes('approver') ? <Col span={12}>
             <Form.Item label="璁剧疆瀹℃壒浜�">
               {getFieldDecorator('approver', {
                 initialValue: data.approver || 'member'
@@ -131,32 +226,19 @@
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' && flowType !== 'reject' ? <Col span={12}>
-            <Form.Item label="瀹℃壒鏂瑰紡">
-              {getFieldDecorator('approvalMethod', {
-                initialValue: data.approvalMethod || 'orsign'
-              })(
-                <Radio.Group>
-                  <Radio value="countersign">浼氱</Radio>
-                  <Radio value="orsign">鎴栫</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {nodetype === 'edge' ? <Col span={12}>
+          {options.includes('members') ? <Col span={12}>
             <Form.Item label="瀹℃壒浜�">
               {getFieldDecorator('members', {
                 initialValue: data.members || [],
-                rules: [{
-                  required: true,
-                  message: '璇锋坊鍔犲鎵逛汉!'
-                }]
+                rules: [
+                  { required: true, message: '璇锋坊鍔犲鎵逛汉!' }
+                ]
               })(
                 <MemberForm orgs={orgs} title="瀹℃壒浜�"/>
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' ? <Col span={12}>
+          {options.includes('copys') ? <Col span={12}>
             <Form.Item label="鎶勯�佷汉">
               {getFieldDecorator('copys', {
                 initialValue: data.copys || []
@@ -165,7 +247,10 @@
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' && flowType !== 'reject' ? <Col span={12}>
+          {options.includes('execCondition') && flowType !== 'reject' ? <Col span={24}>
+            <p className="mk-split">鍒嗘敮鎵ц鏉′欢</p>
+          </Col> : null}
+          {options.includes('execCondition') && flowType !== 'reject' ? <Col span={12}>
             <Form.Item label="鎵ц鏉′欢">
               {getFieldDecorator('execCondition', {
                 valuePropName: 'checked',
@@ -175,7 +260,7 @@
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' && flowType !== 'reject' && execCondition ? <Col span={12}>
+          {flowType !== 'reject' && execCondition ? <Col span={12}>
             <Form.Item label="瀵规瘮鏂瑰紡">
               {getFieldDecorator('match', {
                 initialValue: data.match || '='
@@ -191,7 +276,7 @@
               )}
             </Form.Item>
           </Col> : null}
-          {nodetype === 'edge' && flowType !== 'reject' && execCondition ? <Col span={12}>
+          {flowType !== 'reject' && execCondition ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="瀵规瘮鍊间腑涓嶅彲鍖呭惈鍒惰〃绗︺�佺┖鏍笺�佹崲琛岀绛夈��">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -201,19 +286,53 @@
               {getFieldDecorator('matchVal', {
                 initialValue: data.matchVal || ''
               })(
-                <Input placeholder="" autoComplete="off"/>
+                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
               )}
             </Form.Item>
           </Col> : null}
-          <Col span={24}>
-            <Form.Item label="澶囨敞">
-              {getFieldDecorator('remark', {
-                initialValue: data.remark || ''
+          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' ? <Col span={24}>
+            <p className="mk-split">楂樼骇璁剧疆<span style={{fontSize: '12px', color: 'rgba(0, 0, 0, 0.45)'}}>锛堝惎鐢ㄧ壒娈婂鎵逛汉鏃讹紝绗﹀悎瀹℃壒浜哄垪琛ㄦ椂锛屼紭鍏堜娇鐢ㄦ鍒嗘敮銆傦級</span></p>
+          </Col> : null}
+          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' ? <Col span={12}>
+            <Form.Item label="鐗规畩浜哄憳">
+              {getFieldDecorator('seniorCondition', {
+                valuePropName: 'checked',
+                initialValue: seniorCondition
               })(
-                <TextArea rows={2}/>
+                <Switch checkedChildren="鍚敤" unCheckedChildren="绂佺敤" onChange={(val) => this.setState({seniorCondition: val})} />
               )}
             </Form.Item>
-          </Col>
+          </Col> : null}
+          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' && seniorCondition ? <Col span={12}>
+            <Form.Item label="瀹℃壒浜�">
+              {getFieldDecorator('seniorbers', {
+                initialValue: data.seniorbers || [],
+                rules: [
+                  { required: true, message: '璇锋坊鍔犲鎵逛汉!' }
+                ]
+              })(
+                <MemberForm orgs={orgs} title="瀹℃壒浜�"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {options.includes('senior') && flowType !== 'reject' && approvalMethod !== 'countersign' && seniorCondition ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鐢ㄤ簬涓氬姟澶勭悊鏃剁殑鏍囪鍊粿works_flow_sign@銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鍒嗘敮鏍囪
+              </Tooltip>
+            }>
+              {getFieldDecorator('seniorSign', {
+                initialValue: data.seniorSign || '',
+                rules: [
+                  { required: true, message: '璇锋坊鍔犲垎鏀爣璁�!' },
+                  { pattern: /^[0-9a-zA-Z_]+$/, message: '鍙彲杈撳叆鑻辨枃銆佹暟瀛椾互鍙奯銆�' }
+                ]
+              })(
+                <Input autoComplete="off" onPressEnter={() => this.props.handleSubmit()}/>
+              )}
+            </Form.Item>
+          </Col> : null}
         </Row>
       </Form>
     )
diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
index 75a01b7..ae2dfce 100644
--- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
-import { Spin, Empty, notification, Modal } from 'antd'
+import { Spin, Empty } from 'antd'
 import { DownloadOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -548,8 +548,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -662,37 +662,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -1870,17 +1848,13 @@
           MenuName: menu.MenuName,
           MenuNo: menu.MenuNo || '',
           type: menu.tabType,
-          param: {}
+          param: {$BID: data.$$uuid || ''}
         }
   
-        if (plot.joint === 'true') {
-          newtab.param.$BID = data.$$uuid || ''
-
-          Object.keys(data).forEach(key => {
-            if (/^\$/.test(key)) return
-            newtab.param[key] = data[key]
-          })
-        }
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          newtab.param[key] = data[key]
+        })
   
         MKEmitter.emit('modifyTabs', newtab, true)
       } else if (plot.click === 'menu') {
@@ -1899,16 +1873,12 @@
 
         if (!menu) return
   
-        menu.param = {}
+        menu.param = {$BID: data.$$uuid || ''}
   
-        if (plot.joint === 'true') {
-          menu.param.$BID = data.$$uuid || ''
-
-          Object.keys(data).forEach(key => {
-            if (/^\$/.test(key)) return
-            menu.param[key] = data[key]
-          })
-        }
+        Object.keys(data).forEach(key => {
+          if (/^\$/.test(key)) return
+          menu.param[key] = data[key]
+        })
   
         MKEmitter.emit('modifyTabs', menu, true)
       } else {
diff --git a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
index 15cf833..a9a530a 100644
--- a/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-dashboard/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Chart, registerShape } from '@antv/g2'
-import { Spin, notification, Modal } from 'antd'
+import { Spin } from 'antd'
 // import { DownloadOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -368,37 +368,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx
index 44ed1cc..bc32406 100644
--- a/src/tabviews/custom/components/chart/antv-pie/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
 import DataSet, { DataView } from '@antv/data-set'
-import { Spin, Empty, notification, Modal } from 'antd'
+import { Spin, Empty } from 'antd'
 // import { DownloadOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -316,37 +316,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/chart/antv-scatter/index.jsx b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
index f4751c8..6526bdb 100644
--- a/src/tabviews/custom/components/chart/antv-scatter/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-scatter/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
-import { Spin, Empty, notification, Modal } from 'antd'
+import { Spin, Empty } from 'antd'
 import { DownloadOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
@@ -231,8 +231,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -347,37 +347,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/chart/custom-chart/index.jsx b/src/tabviews/custom/components/chart/custom-chart/index.jsx
index 1fcd7c8..044790e 100644
--- a/src/tabviews/custom/components/chart/custom-chart/index.jsx
+++ b/src/tabviews/custom/components/chart/custom-chart/index.jsx
@@ -4,7 +4,7 @@
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
 import * as echarts from 'echarts'
-import { Spin, Empty, notification, Modal } from 'antd'
+import { Spin, Empty, notification } from 'antd'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -222,8 +222,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -340,37 +340,15 @@
           this.timer && this.timer.stop()
         }
       }
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/code/sand-box/index.jsx b/src/tabviews/custom/components/code/sand-box/index.jsx
index bc158d3..c460bcc 100644
--- a/src/tabviews/custom/components/code/sand-box/index.jsx
+++ b/src/tabviews/custom/components/code/sand-box/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Modal } from 'antd'
+import { Spin, notification } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -261,36 +261,14 @@
         loading: false
       })
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
 
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/editor/braft-editor/index.jsx b/src/tabviews/custom/components/editor/braft-editor/index.jsx
index ccb80cd..0b6db75 100644
--- a/src/tabviews/custom/components/editor/braft-editor/index.jsx
+++ b/src/tabviews/custom/components/editor/braft-editor/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Modal } from 'antd'
+import { Spin } from 'antd'
 
 import asyncComponent from '@/utils/asyncComponent'
 import Api from '@/api'
@@ -211,37 +211,14 @@
         data: _data,
         loading: false
       })
-
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/form/simple-form/index.jsx b/src/tabviews/custom/components/form/simple-form/index.jsx
index b9928e1..d6c4abc 100644
--- a/src/tabviews/custom/components/form/simple-form/index.jsx
+++ b/src/tabviews/custom/components/form/simple-form/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Modal, Button } from 'antd'
+import { Spin, Button } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -267,8 +267,8 @@
       })
     }
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else if (position === 'grid' && config.wrap.datatype === 'static') {
       this.setState({
         data: null
@@ -387,36 +387,13 @@
 
       MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false,
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/form/step-form/index.jsx b/src/tabviews/custom/components/form/step-form/index.jsx
index b22dba9..94fd836 100644
--- a/src/tabviews/custom/components/form/step-form/index.jsx
+++ b/src/tabviews/custom/components/form/step-form/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Button, Modal } from 'antd'
+import { Spin, Button } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -114,6 +114,8 @@
       let s = size * 1.5 + 'px'
       _config.sortStyle = {width: s, height: s, lineHeight: s, borderRadius: s}
     }
+
+    _config.style['--mk-active-color'] = _config.wrap.color || '#1890ff'
 
     this.setState({
       data: _data,
@@ -263,8 +265,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else if (position === 'grid' && config.wrap.datatype === 'static') {
       this.setState({
         data: null
@@ -405,36 +407,13 @@
 
       MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false,
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -480,6 +459,18 @@
     })
   }
 
+  changeGroup = (sort) => {
+    const { config, step } = this.state
+
+    if (config.wrap.labelJump !== 'true' || sort > step) return
+
+    let _group = config.subcards.filter(item => item.sort === sort)[0]
+
+    this.setState({group: null, step: sort - 1}, () => {
+      this.setState({group: _group})
+    })
+  }
+
   render() {
     const { config, loading, BID, BData, data, group, step } = this.state
 
@@ -494,13 +485,14 @@
             <Spin />
           </div> : null
         }
-        {config.wrap.groupLabel !== 'hidden' ? <div className="mk-normal-form-title">
+        {config.wrap.groupLabel !== 'hidden' ? <div className={'mk-normal-form-title' + (config.wrap.labelJump === 'true' ? ' jumpable' : '')}>
           {config.subcards.map(card => (
             <div key={card.uuid} style={config.titleStyle} className={'form-title' + (card.sort <= step ? ' active' : '')}>
-              <span className="form-sort" style={{background: config.wrap.color, ...config.sortStyle}}>{card.sort}</span>
-              <span className="before-line" style={{background: config.wrap.color}}></span>
-              <span className="after-line" style={{background: config.wrap.color}}></span>
-              {card.setting.title}
+              <span className="form-sort" onClick={() => this.changeGroup(card.sort)} style={config.sortStyle}>{card.sort}</span>
+              <br/>
+              <span className="form-label" onClick={() => this.changeGroup(card.sort)}>{card.setting.title}</span>
+              <span className="before-line"></span>
+              <span className="after-line"></span>
             </div>))
           }
         </div> : null}
diff --git a/src/tabviews/custom/components/form/step-form/index.scss b/src/tabviews/custom/components/form/step-form/index.scss
index 6638ab3..edeee82 100644
--- a/src/tabviews/custom/components/form/step-form/index.scss
+++ b/src/tabviews/custom/components/form/step-form/index.scss
@@ -5,6 +5,7 @@
   background-size: cover;
   position: relative;
   min-height: 50px;
+  --mk-active-color: #1890ff;
 
   .mk-normal-form-title {
     display: flex;
@@ -19,7 +20,7 @@
       font-weight: inherit;
       .form-sort {
         background: #d8d8d8;
-        display: block;
+        display: inline-block;
         width: 20px;
         height: 20px;
         line-height: 20px;
@@ -54,11 +55,20 @@
       top: 18px;
     }
     .form-title:not(.active) {
-      .form-sort {
-        background: #d8d8d8!important;
+      .form-sort, .before-line, .after-line {
+        background: #d8d8d8;
       }
-      .before-line, .after-line {
-        background: #d8d8d8!important;
+    }
+    .form-title.active {
+      .form-sort, .before-line, .after-line {
+        background: var(--mk-active-color);
+      }
+    }
+  }
+  .mk-normal-form-title.jumpable {
+    .form-title.active {
+      .form-label, .form-sort {
+        cursor: pointer;
       }
     }
   }
diff --git a/src/tabviews/custom/components/form/tab-form/index.jsx b/src/tabviews/custom/components/form/tab-form/index.jsx
index da36b3c..5bbc94b 100644
--- a/src/tabviews/custom/components/form/tab-form/index.jsx
+++ b/src/tabviews/custom/components/form/tab-form/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Modal } from 'antd'
+import { Spin } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -229,8 +229,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) {
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else if (position === 'grid' && config.wrap.datatype === 'static') {
       this.setState({
         data: null
@@ -339,36 +339,13 @@
 
       MKEmitter.emit('resetSelectLine', config.uuid, _data.$$uuid, _data)
       
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false,
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/group/normal-group/index.jsx b/src/tabviews/custom/components/group/normal-group/index.jsx
index 5a87122..3868f59 100644
--- a/src/tabviews/custom/components/group/normal-group/index.jsx
+++ b/src/tabviews/custom/components/group/normal-group/index.jsx
@@ -1,5 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
+import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
@@ -8,23 +9,32 @@
 
 class NormalGroup extends Component {
   static propTpyes = {
-    config: PropTypes.object,        // 缁勪欢閰嶇疆淇℃伅
+    config: PropTypes.object
   }
 
-  state = {}
+  state = {
+    visible: true,
+    mergeAble: this.props.config.setting.mergeAble === 'true'
+  }
 
   render() {
-    const { config } = this.props
+    const { config, style } = this.props
+    const { visible, mergeAble } = this.state
 
-    if (config.components.length === 0) return (<div style={config.style}></div>)
+    if (config.components.length === 0) return (<div className={'ant-col ant-col-' + config.width} style={style}><div style={config.style}></div></div>)
     
     return (
-      <div className={'normal-group-wrap ' + (config.setting.layout || '')} id={'anchor' + config.uuid} style={config.style}>
-        {config.setting && config.setting.title ? <div className="group-header" style={config.headerStyle}>
-          <span className="title">{config.setting.title}</span>
-        </div> : null}
-        <TabTransfer config={config}/>
-        {/* <Row className="component-wrap">{this.getComponents()}</Row> */}
+      <div className={`ant-col ant-col-${config.width} ${mergeAble ? ' mk-merge-able mk-ctrl-' + (config.setting.ctrlNumber || 1) : ''} ${visible ? '' : ' close'}`} style={style}>
+        <div className={'normal-group-wrap ' + (config.setting.layout || '')} id={'anchor' + config.uuid} style={config.style}>
+          <div className="mk-control">
+            <DoubleLeftOutlined onClick={() => this.setState({visible: false})}/>
+            <DoubleRightOutlined onClick={() => this.setState({visible: true})}/>
+          </div>
+          {config.setting && config.setting.title ? <div className="group-header" style={config.headerStyle}>
+            <span className="title">{config.setting.title}</span>
+          </div> : null}
+          <TabTransfer config={config}/>
+        </div>
       </div>
     )
   }
diff --git a/src/tabviews/custom/components/group/normal-group/index.scss b/src/tabviews/custom/components/group/normal-group/index.scss
index 3869386..a67276f 100644
--- a/src/tabviews/custom/components/group/normal-group/index.scss
+++ b/src/tabviews/custom/components/group/normal-group/index.scss
@@ -13,11 +13,28 @@
       text-decoration: inherit;
       font-weight: inherit;
       font-style: inherit;
+      font-family: inherit;
       float: left;
       line-height: inherit;
       margin-left: 10px;
       position: relative;
       z-index: 1;
+    }
+  }
+
+  .mk-control {
+    display: none;
+    position: absolute;
+    top: 0px;
+    right: 0px;
+    z-index: 2;
+    background: #ffffff;
+    box-shadow: 0px 0px 2px #d8d8d8;
+    transition: all 0.2s;
+
+    .anticon {
+      padding: 5px;
+      cursor: pointer;
     }
   }
 }
@@ -37,4 +54,90 @@
       width: 5%;
     }
   }
+}
+
+.mk-merge-able {
+  transition: all 0.2s;
+
+  .normal-group-wrap {
+    position: relative;
+    transition: all 0.2s;
+  }
+  .mk-control {
+    display: inline-block;
+
+    .anticon-double-left {
+      display: inline-block;
+    }
+    .anticon-double-right {
+      display: none;
+    }
+  }
+}
+
+.mk-merge-able.close {
+  width: 25px;
+  .normal-group-wrap {
+    width: 0px;
+    margin: 0px!important;
+    border-width: 0px!important;
+    box-shadow: none!important;
+  }
+  .mk-control {
+    display: inline-block;
+    right: -24px;
+
+    .anticon-double-left {
+      display: none;
+    }
+    .anticon-double-right {
+      display: inline-block;
+    }
+  }
+}
+
+.mk-merge-able + .ant-col,
+.mk-merge-able + .ant-col + .ant-col,
+.mk-merge-able + .ant-col + .ant-col + .ant-col,
+.mk-merge-able + .ant-col + .ant-col + .ant-col + .ant-col,
+.mk-merge-able + .ant-col + .ant-col + .ant-col + .ant-col + .ant-col {
+  transition: all 0.2s;
+}
+
+.mk-merge-able.close + .ant-col {
+  width: calc(100% - 25px);
+}
+
+.mk-merge-able.close.mk-ctrl-2 + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+
+.mk-merge-able.close.mk-ctrl-3 + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-3 + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+
+.mk-merge-able.close.mk-ctrl-4 + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-4 + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-4 + .ant-col + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+
+.mk-merge-able.close.mk-ctrl-5 + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-5 + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-5 + .ant-col + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
+}
+.mk-merge-able.close.mk-ctrl-5 + .ant-col + .ant-col + .ant-col + .ant-col + .ant-col {
+  width: calc(100% - 25px);
 }
\ No newline at end of file
diff --git a/src/tabviews/custom/components/iframe/index.jsx b/src/tabviews/custom/components/iframe/index.jsx
index 3737715..7e544be 100644
--- a/src/tabviews/custom/components/iframe/index.jsx
+++ b/src/tabviews/custom/components/iframe/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Input, Modal, notification, Empty, Spin } from 'antd'
+import { Input, Empty, Spin } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -212,32 +212,9 @@
         data: _data
       })
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/iframe/index.scss b/src/tabviews/custom/components/iframe/index.scss
index 3e97448..d24ee24 100644
--- a/src/tabviews/custom/components/iframe/index.scss
+++ b/src/tabviews/custom/components/iframe/index.scss
@@ -22,6 +22,7 @@
       font-weight: inherit;
       font-style: inherit;
       line-height: inherit;
+      font-family: inherit;
       margin-left: 10px;
       position: relative;
       z-index: 1;
diff --git a/src/tabviews/custom/components/interfaces/interItem/index.jsx b/src/tabviews/custom/components/interfaces/interItem/index.jsx
index 185a5a6..87e0bd9 100644
--- a/src/tabviews/custom/components/interfaces/interItem/index.jsx
+++ b/src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -1,6 +1,5 @@
 import {Component} from 'react'
 import PropTypes from 'prop-types'
-import { notification, Modal } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -153,39 +152,16 @@
         MKEmitter.emit('interFinish', config.MenuID, config.uuid)
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.loading = false
       this.timer && this.timer.stop()
-      
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
 
       if (config.setting.loadlevel === 'init') {
         MKEmitter.emit('interFinish', config.MenuID, config.uuid)
       }
+
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/module/account/index.jsx b/src/tabviews/custom/components/module/account/index.jsx
index 234db66..0218232 100644
--- a/src/tabviews/custom/components/module/account/index.jsx
+++ b/src/tabviews/custom/components/module/account/index.jsx
@@ -81,6 +81,10 @@
         map.set(item.id, true)
 
         if (item.selected === 'true' && !activeItem) {
+          if (res.invoice_type) {
+            item.invoice_type = res.invoice_type.map(cell => ({value: cell.invoice_type_code, label: cell.invoice_type_name}))
+          }
+          item.$$uuid = item.id
           activeItem = item
         }
         if (item.months) {
diff --git a/src/tabviews/custom/components/module/account/index.scss b/src/tabviews/custom/components/module/account/index.scss
index 1821b31..68b9ba8 100644
--- a/src/tabviews/custom/components/module/account/index.scss
+++ b/src/tabviews/custom/components/module/account/index.scss
@@ -8,8 +8,7 @@
   color: #000000;
 
   .ant-select {
-    min-width: 250px;
-    max-width: 300px;
+    width: 270px;
     color: #000000;
   }
 
diff --git a/src/tabviews/custom/components/module/invoice/index.jsx b/src/tabviews/custom/components/module/invoice/index.jsx
new file mode 100644
index 0000000..e50407c
--- /dev/null
+++ b/src/tabviews/custom/components/module/invoice/index.jsx
@@ -0,0 +1,1284 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Select, Form, Input, Button, Modal, Spin, notification } from 'antd'
+import { EllipsisOutlined, LeftOutlined } from '@ant-design/icons'
+import moment from 'moment'
+import md5 from 'md5'
+
+import Api from '@/api'
+import UtilsDM from '@/utils/utils-datamanage.js'
+import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
+import InvoiceTable from './invoiceTable'
+import SubTable from './subTable'
+import './index.scss'
+
+class InvoiceModule extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {
+    BID: '',
+    ID: Utils.getguid(),
+    io: '',
+    invTypes: [],
+    invoice_type: '',
+    business_type: '',
+    date: moment().format('YYYY骞碝M鏈圖D鏃�'),
+    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: '',
+    payee: '',
+    reviewer: '',
+    drawer: '',
+    details: [],
+    oriDetails: [],
+    book: null,
+    loading: false,
+    saveType: '',
+    tax_type: '',
+    reqfields: [],
+    requireds: [],
+    invoice_no: '',
+    invoice_code: '',
+    invoice_date: '',
+    read_only: false,
+    invoice_type_name: '',
+    timestamp: ''
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    let _config = fromJS(config).toJS()
+    let BID = ''
+    let BData = ''
+
+    if (_config.setting.supModule) {
+      BData = window.GLOB.CacheData.get(_config.setting.supModule)
+    } else {
+      BData = window.GLOB.CacheData.get(_config.$pageId)
+    }
+    if (BData) {
+      BID = BData.$BID || ''
+    }
+
+    if (_config.wrap.invColor) {
+      _config.style['--inv-color'] = _config.wrap.invColor
+    }
+
+    _config.buyer = this.formatSetting(_config.buyer, 'buyer')
+    _config.detail = this.formatSetting(_config.detail, 'detail')
+    _config.detail.uuid = _config.uuid
+
+    let book = null
+    let pas = {}
+    if (config.wrap.supBook) {
+      book = window.GLOB.CacheData.get(config.wrap.supBook) || null
+
+      if (book) {
+        pas = this.resetParam(book)
+      }
+    }
+
+    this.setState({
+      BID: BID || '',
+      config: _config,
+      book,
+      ...pas
+    })
+  }
+
+  componentDidMount () {
+    const { config } = this.props
+
+    MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+
+    if (config.wrap.datatype === 'dynamic' && config.setting.onload === 'true') {
+      setTimeout(() => {
+        this.loadData()
+      }, config.setting.delay || 0)
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
+  }
+
+  formatSetting = (item, type) => {
+    item.setting.arr_field = item.columns.map(col => col.field).join(',')
+    item.setting.laypage = item.setting.laypage === 'true'
+
+    if (item.refreshTab && item.refreshTab.length) {
+      item.reTabId = item.refreshTab.pop()
+    }
+    if (item.syncComponent && item.syncComponent.length) {
+      item.syncComId = item.syncComponent.pop()
+    }
+
+    if (type === 'buyer') {
+      item.columns = item.columns.map(cell => {
+        if (['from_to_tel', 'from_to_account_no', 'from_to_code'].includes(cell.field)) {
+          cell.Hide = 'true'
+        } else if (['from_to_email', 'from_to_mob'].includes(cell.field)) {
+          cell.Width = 80
+        } else if (['from_to_name'].includes(cell.field)) {
+          cell.Width = 140
+        }
+        return cell
+      })
+    } else {
+      item.columns = item.columns.map(cell => {
+        if (cell.field === 'general_tax_rate') {
+          cell.field = 'tax_rate'
+          cell.label = '绋庣巼'
+        }
+        if (['Description', 'id', 'small_tax_rate', 'free_tax_mark', 'vat_special_management', 'tax_item', 'tax_method'].includes(cell.field)) {
+          cell.Hide = 'true'
+        } else if (['spec'].includes(cell.field)) {
+          cell.Width = 150
+        } else if (['unit', 'unitprice', 'tax_rate'].includes(cell.field)) {
+          cell.Width = 80
+        }
+
+        return cell
+      })
+    }
+
+    if (item.setting.interType !== 'system') {
+      item.setting.dataresource = ''
+      return item
+    }
+
+    let regs = [
+      { reg: /@userName@/ig, value: `'${sessionStorage.getItem('User_Name') || ''}'` },
+      { reg: /@fullName@/ig, value: `'${sessionStorage.getItem('Full_Name') || ''}'` }
+    ]
+    
+    if (window.GLOB.externalDatabase !== null) {
+      regs.push({
+        reg: /@db@/ig,
+        value: window.GLOB.externalDatabase
+      })
+    }
+
+    let _customScript = ''
+    let _tailScript = ''
+    item.scripts && item.scripts.forEach(script => {
+      if (script.status === 'false') return
+      if (script.position !== 'back') {
+        _customScript += `
+        ${script.sql}
+        `
+      } else {
+        _tailScript += `
+        ${script.sql}
+        `
+      }
+    })
+    delete item.scripts
+
+    item.setting.execute = item.setting.execute !== 'false'
+    
+    if (!item.setting.execute) {
+      item.setting.dataresource = ''
+    }
+    if (/\s/.test(item.setting.dataresource)) {
+      item.setting.dataresource = '(' + item.setting.dataresource + ') tb'
+    }
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      item.setting.dataresource = item.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+      _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+      _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+    } else {
+      item.setting.dataresource = item.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+      _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+      _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+    }
+
+    regs.forEach(cell => {
+      item.setting.dataresource = item.setting.dataresource.replace(cell.reg, cell.value)
+      _customScript = _customScript.replace(cell.reg, cell.value)
+      _tailScript = _tailScript.replace(cell.reg, cell.value)
+    })
+
+    item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+    item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
+
+    item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
+
+    return item
+  }
+
+  resetParentParam = (MenuID, id, data) => {
+    const { config } = this.state
+
+    if (config.wrap.supBook === MenuID) {
+      let pas = this.resetParam(data)
+
+      this.setState({ book: data, ...pas }, () => {
+        this.loadData()
+      })
+      return
+    }
+
+    if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return
+    if (id !== this.state.BID || id !== '') {
+      this.setState({ BID: id }, () => {
+        this.loadData()
+      })
+    }
+  }
+
+  resetParam = (book) => {
+    let invTypes = book.invoice_type || []
+    let invoice_type = sessionStorage.getItem('pre_invoice_type') || ''
+    if (invoice_type && invTypes.findIndex(item => item.value === invoice_type) === -1) {
+      invoice_type = ''
+    }
+
+    this.getRequired(invoice_type)
+
+    return {
+      invoice_type,
+      invTypes: invTypes,
+      orgname: book.orgname || '',
+      tax_no: book.tax_no || '',
+      addr: book.addr || '',
+      tel: book.tel || '',
+      bank_name: book.bank_name || '',
+      account_no: book.account_no || '',
+      payee: book.payee || '',
+      reviewer: book.reviewer || '',
+      drawer: book.drawer || '',
+      tax_type: book.tax_type || ''
+    }
+  }
+
+  reloadData = (menuId) => {
+    const { config } = this.state
+    
+    if (config.uuid !== menuId) return
+
+    this.loadData()
+  }
+
+  async loadData() {
+    const { config, BID, book } = this.state
+
+    if (config.wrap.datatype !== 'dynamic' || !book) return
+    if (!BID) {
+      this.clearData()
+      return
+    }
+
+    let param = UtilsDM.getQueryDataParams(config.setting, [], config.setting.order, 1, 1, BID)
+
+    this.setState({
+      loading: true
+    })
+
+    let result = await Api.genericInterface(param)
+    if (result.status) {
+      if (!result.data[0]) {
+        this.clearData()
+        this.setState({
+          loading: false
+        })
+        return
+      }
+
+      let line = result.data[0]
+      let details = result.data.map(item => {
+        let tax_name = item.tax_rate * 100 + '%'
+
+        if (item.vat_special_management && item.free_tax_mark === 'true') {
+          tax_name = item.vat_special_management
+        }
+
+        return {
+          uuid: item.jskey,
+          productname: item.productname,
+          productcode: item.productcode,
+          spec: item.spec,
+          unit: item.unit,
+          bill_count: item.bill_count,
+          unitprice: item.unitprice,
+          tax_rate: item.tax_rate,
+          free_tax_mark: item.free_tax_mark,
+          vat_special_management: item.vat_special_management,
+          tax_classify_code: item.tax_classify_code,
+          tax_classify_name: item.tax_classify_name,
+          amount_line: item.amount_line,
+          tax_amount: item.tax_amount,
+          invoice_lp: item.invoice_lp,
+          tax_item: item.tax_item,
+          tax_method: item.tax_method,
+          tax_name: tax_name
+        }
+      })
+
+      let invoice_type_name = ''
+      if (line.read_only === 'true') {
+        let types = book.invoice_type || []
+        types.forEach(item => {
+          if (item.value === line.invoice_type) {
+            invoice_type_name = item.label
+          }
+        })
+        invoice_type_name = invoice_type_name || line.invoice_type
+      }
+
+      this.setState({
+        ID: line[config.setting.primaryKey] || Utils.getguid(),
+        io: line.io,
+        invoice_type: line.invoice_type,
+        business_type: line.business_type,
+        from_to_name: line.from_to_name,
+        from_to_tax_no: line.from_to_tax_no,
+        from_to_addr: line.from_to_addr,
+        from_to_tel: line.from_to_tel,
+        from_to_bank_name: line.from_to_bank_name,
+        from_to_account_no: line.from_to_account_no,
+        from_to_mob: line.from_to_mob,
+        from_to_email: line.from_to_email,
+        from_to_code: line.from_to_code,
+        orgname: line.orgname,
+        tax_no: line.tax_no,
+        addr: line.addr,
+        tel: line.tel,
+        bank_name: line.bank_name,
+        account_no: line.account_no,
+        remark: line.remark,
+        payee: line.payee,
+        reviewer: line.reviewer,
+        drawer: line.drawer,
+        details: details,
+        invoice_no: line.invoice_no,
+        invoice_code: line.invoice_code,
+        invoice_date: line.read_only === 'true' ? line.invoice_date : '',
+        read_only: line.read_only === 'true',
+        invoice_type_name: invoice_type_name,
+        oriDetails: fromJS(details).toJS(),
+        timestamp: new Date().getTime() + '',
+        loading: false
+      })
+
+      this.getRequired(line.invoice_type)
+
+      UtilsDM.querySuccess(result)
+    } else {
+      this.setState({
+        loading: false
+      })
+      this.timer && this.timer.stop()
+
+      UtilsDM.queryFail(result)
+    }
+  }
+
+  clearData = () => {
+    this.setState({
+      ID: Utils.getguid(),
+      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: '',
+      business_type: '',
+      details: [],
+      oriDetails: [],
+      timestamp: new Date().getTime() + '',
+    })
+  }
+
+  changeType = (val) => {
+    sessionStorage.setItem('pre_invoice_type', val)
+    this.setState({invoice_type: val})
+    this.getRequired(val)
+  }
+
+  getRequired = (invoice_type) => {
+    if (!invoice_type) {
+      this.setState({
+        reqfields: [],
+        requireds: []
+      })
+      return
+    }
+
+    let reqfields = []
+    let requireds = []
+    let rds = [
+      {value: 'from_to_name', label: '璐拱鏂瑰悕绉�'},
+      {value: 'from_to_tax_no', label: '璐拱鏂圭撼绋庝汉璇嗗埆鍙�'},
+      {value: 'from_to_addr', label: '璐拱鏂瑰湴鍧�'},
+      {value: 'from_to_tel', label: '璐拱鏂圭數璇�'},
+      {value: 'from_to_bank_name', label: '璐拱鏂瑰紑鎴疯'},
+      {value: 'from_to_account_no', label: '璐拱鏂硅处鍙�'},
+      {value: 'from_to_mob', label: '璐拱鏂规墜鏈哄彿'},
+      {value: 'from_to_email', label: '璐拱鏂归偖绠�'},
+
+      {value: 'orgname', label: '閿�鍞柟鍚嶇О'},
+      {value: 'tax_no', label: '閿�鍞柟绾崇◣浜鸿瘑鍒彿'},
+      {value: 'addr', label: '閿�鍞柟鍦板潃'},
+      {value: 'tel', label: '閿�鍞柟鐢佃瘽'},
+      {value: 'bank_name', label: '閿�鍞柟寮�鎴疯'},
+      {value: 'account_no', label: '閿�鍞柟璐﹀彿'},
+    ]
+    if (invoice_type === 'e_general') {
+      reqfields = ['from_to_name', 'from_to_tax_no', 'orgname', 'tax_no']
+      rds.forEach(item => {
+        if (reqfields.includes(item.value)) {
+          requireds.push(item)
+        }
+      })
+    } else if (invoice_type === 'e_special') {
+      reqfields = ['from_to_name', 'from_to_tax_no', 'from_to_addr', 'from_to_tel', 'from_to_bank_name', 'from_to_account_no', 'orgname', 'tax_no', 'addr', 'tel', 'bank_name', 'account_no']
+      rds.forEach(item => {
+        if (reqfields.includes(item.value)) {
+          requireds.push(item)
+        }
+      })
+    }
+    
+    this.setState({
+      reqfields,
+      requireds
+    })
+  }
+
+  saveBill = () => {
+    const { config, BID, saveType } = this.state
+
+    if (saveType) return
+
+    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
+        }
+  
+        param.secretkey = Utils.encrypt('', param.timestamp)
+        param.LText = Utils.formatOptions(param.LText, param.exec_type)
+
+        this.setState({
+          saveType: 'bill'
+        })
+
+        Api.genericInterface(param).then(res => {
+          this.setState({
+            saveType: ''
+          })
+          if (res.status) {
+            if (config.billSaveBtn.reTabId) {
+              MKEmitter.emit('reloadMenuView', config.billSaveBtn.reTabId, 'table')
+            }
+            if (config.billSaveBtn.syncComId) {
+              MKEmitter.emit('reloadData', config.billSaveBtn.syncComId)
+            }
+            notification.success({
+              top: 92,
+              message: '淇濆瓨鎴愬姛銆�',
+              duration: 5
+            })
+          } else {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+          }
+        })
+      }, (error) => {
+        notification.warning({
+          top: 92,
+          message: error,
+          duration: 5
+        })
+      })
+    }, 20)
+  }
+
+  outBill = () => {
+    const { config, BID, saveType } = this.state
+
+    if (window.GLOB.systemType === 'production' && !config.billOutBtn.proInterface) {
+      notification.warning({
+        top: 92,
+        message: '灏氭湭璁剧疆姝e紡绯荤粺鎺ュ彛鍦板潃锛�',
+        duration: 5
+      })
+      return
+    }
+
+    if (saveType) return
+
+    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
+        }
+  
+        param.secretkey = Utils.encrypt('', param.timestamp)
+        param.LText = Utils.formatOptions(param.LText, param.exec_type)
+
+        this.setState({
+          saveType: 'out'
+        })
+
+        Api.genericInterface(param).then(res => {
+          if (res.status) {
+            this.outPutBill(res)
+          } else {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            this.setState({
+              saveType: ''
+            })
+          }
+        })
+      }, (error) => {
+        notification.warning({
+          top: 92,
+          message: error,
+          duration: 5
+        })
+        return
+      })
+    })
+  }
+
+  goback = () => {
+    const { config } = this.state
+    MKEmitter.emit('closeTabView', config.$pageId)
+  }
+
+  getPreSql = (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 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') || ''
+    let options = fromJS(oriDetails).toJS()
+    let price = 0
+    let tax = 0
+
+    let lines = []
+    details.forEach(line => {
+      if (!line.productcode) return
+
+      let _sql = `Select '${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
+        })
+      }
+
+      lines.push(_sql + `, '${data_type}'`)
+    })
+
+    let _total = (price - tax) / 100
+    price = price / 100
+    tax = tax / 100
+
+    if (options.length) {
+      options.forEach(line => {
+        lines.push(`Select '${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 = lines.join(' union all ')
+
+    let _script = ''
+    btn.scripts.forEach(item => {
+      if (item.status === 'false') return
+      _script += `
+      ${item.sql}
+      `
+    })
+
+    let sql = `/* 绯荤粺瀛楁 */
+      Declare @UserName nvarchar(50), @FullName nvarchar(50), @RoleID nvarchar(512), @mk_departmentcode nvarchar(512), @mk_organization nvarchar(512), @mk_user_type nvarchar(20), @mk_nation nvarchar(50), @mk_province nvarchar(50), @mk_city nvarchar(50), @mk_district nvarchar(50), @mk_address nvarchar(100), @ErrorCode nvarchar(50), @retmsg nvarchar(4000), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
+
+      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID}'
+
+      /* 鍙戠エ涓昏〃瀛楁 */
+      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='${book.orgcode || ''}', @total_net_amount=${_total}, @total_tax=${tax}, @total_amount=${price}, @business_type='${business_type || config.wrap.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)
+
+      ${lines}
+
+      /* 鑷畾涔夎剼鏈� */
+      ${_script}
+      `
+
+    if (btn.type === 'billout') {
+      sql += `aaa: if @ErrorCode!=''
+      insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg, @UserID@`
+    } 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(/@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) {
+      console.info(sql.replace(/\n\s{6}/ig, '\n'))
+    }
+
+    return sql
+  }
+
+  getBillMsg = () => {
+    const { requireds, invoice_type, details, remark, from_to_addr, addr } = this.state
+
+    return new Promise((resolve, reject) => {
+      let error = ''
+
+      if (!invoice_type) {
+        error = '璇烽�夋嫨鍙戠エ绫诲瀷锛�'
+      }
+      
+      if (!error) {
+        requireds.forEach(item => {
+          if (!this.state[item.value] && !error) {
+            error = '璇疯緭鍏�' + item.label + '锛�'
+          }
+        })
+      }
+
+      if (!error && remark.length > 512) {
+        error = '澶囨敞涓嶅彲瓒呰繃512涓瓧绗︼紒'
+      }
+      if (!error && from_to_addr.length > 100) {
+        error = '璐拱鏂瑰湴鍧�涓嶅彲瓒呰繃100涓瓧绗︼紒'
+      }
+      if (!error && addr.length > 100) {
+        error = '閿�鍞柟鍦板潃涓嶅彲瓒呰繃100涓瓧绗︼紒'
+      }
+
+      if (!error) {
+        if (details.length === 0 || details.filter(line => !!line.productcode).length === 0) {
+          error = '璇锋坊鍔犳槑缁嗭紒'
+        } else {
+          details.forEach((line, index) => {
+            if (error) return
+            if (line.productcode) {
+              if (!line.bill_count) {
+                error = '鏄庣粏绗�' + (index + 1) + '琛岋紝璇疯緭鍏ユ暟閲忥紒'
+              } else if (!line.unitprice) {
+                error = '鏄庣粏绗�' + (index + 1) + '琛岋紝璇疯緭鍏ュ崟浠凤紒'
+              }
+            }
+          })
+        }
+      }
+
+      if (error) {
+        reject(error)
+      } else {
+        resolve()
+      }
+    })
+  }
+
+  outPutBill = (res) => {
+    const { config } = this.state
+
+    if (!res.data_invoice || !res.sellerName || !res.taxNo) {
+      notification.warning({
+        top: 92,
+        message: '缂哄皯寮�绁ㄥ弬鏁帮紒',
+        duration: 5
+      })
+      this.setState({
+        saveType: ''
+      })
+    }
+
+    let param = {
+      data: res.data_invoice,
+      sellerName: res.sellerName,
+      taxNo: res.taxNo
+    }
+
+    let trans = {
+      e_general: '02',
+      e_special: '01'
+    }
+
+    param.data.invoiceTypeCode = trans[param.data.invoiceTypeCode] || ''
+
+    let url = ''
+    if (window.GLOB.systemType === 'production') {
+      url = config.billOutBtn.proInterface
+    } else {
+      url = config.billOutBtn.interface
+    }
+    if (!/^http/.test(url)) {
+      url = window.location.origin + url
+    }
+
+    let _params = {
+      url: url,
+      method: 'post',
+      headers: { 'Content-Type': 'application/json' },
+      data: param
+    }
+
+    Api.directRequest(_params).then(result => {
+      result.mk_api_key = res.mk_api_key || ''
+      this.callBackBill(result)
+    })
+  }
+
+  callBackBill = (result) => {
+    const { config, BID, ID } = this.state
+
+    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) {
+                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, '"')
+          }
+          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]
+        })
+      }
+    })
+
+    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}
+      `
+      }
+    })
+
+    _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'
+    }
+
+    Api.genericInterface(param).then(res => {
+      this.setState({
+        saveType: ''
+      })
+      if (res.status) {
+        if (config.billOutBtn.reTabId) {
+          MKEmitter.emit('reloadMenuView', config.billOutBtn.reTabId, 'table')
+        }
+        if (config.billOutBtn.syncComId) {
+          MKEmitter.emit('reloadData', config.billOutBtn.syncComId)
+        }
+        this.clearData()
+
+        notification.success({
+          top: 92,
+          message: '寮�绁ㄦ垚鍔熴��',
+          duration: 5
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  getBackSql = () => {
+    const { book, BID } = this.state
+
+    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') || ''
+
+    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), @account_id nvarchar(50), @account_year_id nvarchar(50), @account_code nvarchar(50), @account_year_code nvarchar(50), @bid nvarchar(50), @tbid nvarchar(50)
+
+      Select @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}', @ErrorCode='', @retmsg='', @account_id='${book.account_id || ''}', @account_year_id='${book.account_year_id || ''}', @account_code='${book.account_code || ''}', @account_year_code='${book.account_year_code || ''}', @bid='${BID || ''}'
+
+      `
+
+    return sql
+  }
+
+  changeBuyer = (item) => {
+    this.setState({
+      visible: false,
+      from_to_name: item.from_to_name || '',
+      from_to_tax_no: item.from_to_tax_no || '',
+      from_to_addr: item.from_to_addr || '',
+      from_to_tel: item.from_to_tel || '',
+      from_to_bank_name: item.from_to_bank_name || '',
+      from_to_account_no: item.from_to_account_no || '',
+      from_to_mob: item.from_to_mob || '',
+      from_to_email: item.from_to_email || '',
+      from_to_code: item.from_to_code || '',
+    })
+  }
+
+  addInvice = () => {
+    const { saveType } = this.state
+
+    if (saveType) {
+      notification.warning({
+        top: 92,
+        message: saveType === 'bill' ? '鍗曟嵁淇濆瓨涓紝璇风◢鍚庛��' : '寮�绁ㄤ腑锛岃绋嶅悗銆�',
+        duration: 3
+      })
+      return
+    }
+
+    this.clearData()
+
+    notification.success({
+      top: 92,
+      message: '鍗曟嵁宸叉洿鏂般��',
+      duration: 3
+    })
+  }
+
+  // jumpSys = () => {
+  //   window.open(`${window.location.origin}/kgcs/thirdPlatFormLogin?userName=admin&taxCode=91120222MA07GMNW97&taxName=澶╂触鐣呬韩鏁板瓧绉戞妧鏈夐檺鍏徃`)
+  // }
+
+  render() {
+    const { config, book, loading, invTypes, reqfields, saveType, date, timestamp, 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, orgname, tax_no, addr, tel, bank_name, account_no, remark, reviewer, drawer, payee, details, visible, tax_type, invoice_no, invoice_code, invoice_date, read_only, invoice_type_name } = this.state
+
+    if (!book || (config.wrap.datatype === 'dynamic' && !timestamp)) {
+      return <div className="menu-invoice-wrap" style={config.style}>
+        <div className="loading-mask">
+          <div className="ant-spin-blur"></div>
+          <Spin />
+        </div>
+      </div>
+    }
+
+    if (read_only) {
+      return (
+        <div className="menu-invoice-wrap read_only" style={config.style}>
+          {loading ?
+            <div className="loading-mask">
+              <div className="ant-spin-blur"></div>
+              <Spin />
+            </div> : null
+          }
+          <div className="inv-action">
+            {config.wrap.backBtn === 'show' ? <Button className="mk-back" onClick={this.goback}><LeftOutlined />杩斿洖</Button> : null}
+          </div>
+          <div className="inv-header">
+            <div className="inv-type">{invoice_type_name}</div>
+            <div className="inv-msg">
+              {invoice_no ? <div>鍙戠エ鍙风爜锛歿invoice_no}</div> : null}
+              {invoice_code ? <div>鍙戠エ浠g爜锛歿invoice_code}</div> : null}
+              {invoice_date ? <div>寮�绁ㄦ棩鏈燂細{invoice_date}</div> : null}
+            </div>
+          </div>
+          <div className="inv-body">
+            <div className="inv-main-content">
+              <div className="inv-buyer">
+                <div className="inv-label">璐拱鏂�</div>
+                <div className="inv-content">
+                  <Form.Item className="mk-name" label={<>鍚�<span></span>绉�</>}>
+                    {from_to_name}
+                  </Form.Item>
+                  <Form.Item label="绾崇◣浜鸿瘑鍒彿">
+                    {from_to_tax_no}
+                  </Form.Item>
+                  <Form.Item label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}>
+                    {from_to_addr + ' ' + from_to_tel}
+                  </Form.Item>
+                  <Form.Item label="寮�鎴疯鍙婅处鍙�">
+                    {from_to_bank_name + ' ' + from_to_account_no}
+                  </Form.Item>
+                </div>
+              </div>
+              <div className="inv-notice">
+                <div className="inv-label">閫氱煡鍒�</div>
+                <div className="inv-content">
+                  <Form.Item label={<>鎵�<span></span>鏈�<span></span>鍙�</>}>
+                    {from_to_mob}
+                  </Form.Item>
+                  <Form.Item label={<>閭�<span></span>绠�</>}>
+                    {from_to_email}
+                  </Form.Item>
+                </div>
+              </div>
+            </div>
+            <div className="inv-details">
+              <InvoiceTable data={details} timestamp={timestamp} read_only={true} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
+            </div>
+            <div className="inv-main-content">
+              <div className="inv-buyer">
+                <div className="inv-label">閿�鍞柟</div>
+                <div className="inv-content">
+                  <Form.Item label={<>鍚�<span></span>绉�</>}>
+                    {orgname}
+                  </Form.Item>
+                  <Form.Item label="绾崇◣浜鸿瘑鍒彿">
+                    {tax_no}
+                  </Form.Item>
+                  <Form.Item label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}>
+                    {addr + ' ' + tel}
+                  </Form.Item>
+                  <Form.Item label="寮�鎴疯鍙婅处鍙�">
+                    {bank_name + ' ' + account_no}
+                  </Form.Item>
+                </div>
+              </div>
+              <div className="inv-notice">
+                <div className="inv-label">澶囨敞</div>
+                <div className="inv-content" style={{paddingTop: '30px'}}>
+                  <Form.Item label="">
+                    {remark}
+                  </Form.Item>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div className="inv-tail">
+            <Form.Item label="鏀舵浜�">
+              {payee}
+            </Form.Item>
+            <Form.Item label="澶嶆牳浜�">
+              {reviewer}
+            </Form.Item>
+            <Form.Item label="寮�绁ㄤ汉">
+              {drawer}
+            </Form.Item>
+          </div>
+        </div>
+      )
+    }
+
+    return (
+      <div className="menu-invoice-wrap" style={config.style}>
+        {loading ?
+          <div className="loading-mask">
+            <div className="ant-spin-blur"></div>
+            <Spin />
+          </div> : null
+        }
+        <div className="inv-action">
+          {config.wrap.backBtn === 'show' ? <Button className="mk-back" onClick={this.goback}><LeftOutlined />杩斿洖</Button> : null}
+          {/* <Button className="mk-addinv" onClick={this.jumpSys}>璺宠浆</Button> */}
+          <Button className="mk-addinv" onClick={this.addInvice}>鏂板鍙戠エ</Button>
+          <Button className="mk-bill" loading={saveType === 'bill'} onClick={this.saveBill}>淇濆瓨鍗曟嵁</Button>
+          <Button className="mk-submit" loading={saveType === 'out'} onClick={this.outBill}>鎻愪氦寮�绁�</Button>
+        </div>
+        <div className="inv-header">
+          {invoice_type ? <Select value={invoice_type} onChange={this.changeType} dropdownClassName="inv-type-select">
+            {invTypes.map(item => (
+              <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
+            ))}
+          </Select> : <Select placeholder="璇烽�夋嫨鍙戠エ绉嶇被" onChange={this.changeType} dropdownClassName="inv-type-select">
+            {invTypes.map(item => (
+              <Select.Option key={item.value} value={item.value}>{item.label}</Select.Option>
+            ))}
+          </Select>}
+          <div className="date">寮�绁ㄦ棩鏈燂細{date}</div>
+        </div>
+        <div className="inv-body">
+          <div className="inv-main-content">
+            <div className="inv-buyer">
+              <div className="inv-label">璐拱鏂�</div>
+              <div className="inv-content">
+                <Form.Item className="mk-name" required={reqfields.includes('from_to_name')} label={<>鍚�<span></span>绉�</>} extra={<EllipsisOutlined onClick={() => this.setState({visible: true})}/>}>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟鍚嶇О" allowClear value={from_to_name} autoComplete="off" onChange={(e) => this.setState({from_to_name: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('from_to_tax_no')} label="绾崇◣浜鸿瘑鍒彿">
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟绾崇◣浜鸿瘑鍒彿" allowClear value={from_to_tax_no} autoComplete="off" onChange={(e) => this.setState({from_to_tax_no: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('from_to_addr')} className="mutil-input" label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟鍦板潃" allowClear value={from_to_addr} autoComplete="off" onChange={(e) => this.setState({from_to_addr: e.target.value})}/>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟鐢佃瘽" allowClear value={from_to_tel} autoComplete="off" onChange={(e) => this.setState({from_to_tel: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('from_to_bank_name')} className="mutil-input" label="寮�鎴疯鍙婅处鍙�">
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟寮�鎴疯" allowClear value={from_to_bank_name} autoComplete="off" onChange={(e) => this.setState({from_to_bank_name: e.target.value})}/>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟璐﹀彿" allowClear value={from_to_account_no} autoComplete="off" onChange={(e) => this.setState({from_to_account_no: e.target.value})}/>
+                </Form.Item>
+              </div>
+            </div>
+            <div className="inv-notice">
+              <div className="inv-label">閫氱煡鍒�</div>
+              <div className="inv-content">
+                <Form.Item required={reqfields.includes('from_to_mob')} label={<>鎵�<span></span>鏈�<span></span>鍙�</>}>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟鎵嬫満鍙�" allowClear value={from_to_mob} autoComplete="off" onChange={(e) => this.setState({from_to_mob: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('from_to_email')} label={<>閭�<span></span>绠�</>}>
+                  <Input placeholder="璇疯緭鍏ヨ喘涔版柟閭" allowClear value={from_to_email} autoComplete="off" onChange={(e) => this.setState({from_to_email: e.target.value})}/>
+                </Form.Item>
+              </div>
+            </div>
+          </div>
+          <div className="inv-details">
+            <InvoiceTable data={details} timestamp={timestamp} read_only={false} config={config.detail} tax_type={tax_type} onChange={(details) => this.setState({details})}/>
+          </div>
+          <div className="inv-main-content">
+            <div className="inv-buyer">
+              <div className="inv-label">閿�鍞柟</div>
+              <div className="inv-content">
+                <Form.Item required={reqfields.includes('orgname')} label={<>鍚�<span></span>绉�</>}>
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟鍚嶇О" value={orgname} autoComplete="off" onChange={(e) => this.setState({orgname: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('tax_no')} label="绾崇◣浜鸿瘑鍒彿">
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟绾崇◣浜鸿瘑鍒彿" disabled value={tax_no} autoComplete="off"/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('addr')} className="mutil-input" label={<>鍦�<span></span>鍧�<span></span>銆�<span></span>鐢�<span></span>璇�</>}>
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟鍦板潃" value={addr} autoComplete="off" onChange={(e) => this.setState({addr: e.target.value})}/>
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟鐢佃瘽" value={tel} autoComplete="off" onChange={(e) => this.setState({tel: e.target.value})}/>
+                </Form.Item>
+                <Form.Item required={reqfields.includes('bank_name')} className="mutil-input" label="寮�鎴疯鍙婅处鍙�">
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟寮�鎴疯" value={bank_name} autoComplete="off" onChange={(e) => this.setState({bank_name: e.target.value})}/>
+                  <Input placeholder="璇疯緭鍏ラ攢鍞柟璐﹀彿" value={account_no} autoComplete="off" onChange={(e) => this.setState({account_no: e.target.value})}/>
+                </Form.Item>
+              </div>
+            </div>
+            <div className="inv-notice">
+              <div className="inv-label">澶囨敞</div>
+              <div className="inv-content" style={{paddingTop: '30px'}}>
+                <Form.Item label="">
+                  <Input.TextArea placeholder="璇疯緭鍏ュ娉�" autoSize={{ minRows: 4, maxRows: 4 }} value={remark} autoComplete="off" onChange={(e) => this.setState({remark: e.target.value})}/>
+                </Form.Item>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div className="inv-tail">
+          <Form.Item label="鏀舵浜�">
+            <Input placeholder="鏀舵浜�" value={payee} autoComplete="off" onChange={(e) => this.setState({payee: e.target.value})}/>
+          </Form.Item>
+          <Form.Item label="澶嶆牳浜�">
+            <Input placeholder="澶嶆牳浜�" value={reviewer} autoComplete="off" onChange={(e) => this.setState({reviewer: e.target.value})}/>
+          </Form.Item>
+          <Form.Item label="寮�绁ㄤ汉">
+            <Input placeholder="寮�绁ㄤ汉" value={drawer} autoComplete="off" onChange={(e) => this.setState({drawer: e.target.value})}/>
+          </Form.Item>
+        </div>
+        <Modal
+          title="瀹㈡埛淇℃伅"
+          visible={visible}
+          width="75vw"
+          maskClosable={false}
+          onCancel={() => { this.setState({ visible: false }) }}
+          footer={null}
+        >
+          <SubTable config={config.buyer} onChange={this.changeBuyer}/>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default InvoiceModule
\ No newline at end of file
diff --git a/src/tabviews/custom/components/module/invoice/index.scss b/src/tabviews/custom/components/module/invoice/index.scss
new file mode 100644
index 0000000..1ec31ae
--- /dev/null
+++ b/src/tabviews/custom/components/module/invoice/index.scss
@@ -0,0 +1,361 @@
+.menu-invoice-wrap {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  color: #000000;
+  min-height: 500px;
+  --inv-color: #13509c;
+
+  .inv-action {
+    text-align: right;
+    margin-right: 30px;
+    .ant-btn {
+      margin-left: 15px;
+      margin-bottom: 5px;
+      height: 30px;
+    }
+    .mk-back {
+      border: none;
+      float: left;
+      margin-left: 0px;
+      padding: 0px;
+      box-shadow: none;
+    }
+    .mk-back::after {
+      display: none;
+    }
+    .mk-back:hover, .mk-back:active, .mk-back:focus {
+      color: var(--mk-sys-color);
+    }
+    .mk-addinv, .mk-addinv:active, .mk-addinv:focus {
+      color: #52c41a;
+      border-color: #52c41a;
+    }
+    .mk-bill:hover, .mk-bill:active, .mk-bill:focus {
+      color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+    .mk-submit, .mk-submit:hover, .mk-submit:active, .mk-submit:focus {
+      color: #fff;
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+    }
+  }
+  .inv-header {
+    text-align: center;
+    position: relative;
+    height: 70px;
+    margin-right: 30px;
+    .inv-type {
+      width: 390px;
+      display: inline-block;
+      position: relative;
+      font-size: 25px;
+      text-align: center;
+      font-family: kaiti;
+      color: var(--inv-color, #13509c);
+    }
+    .inv-type::before, .inv-type::after {
+      content: '';
+      display: block;
+      width: 100%;
+      position: absolute;
+      border-top: var(--inv-color, #13509c) 1px solid;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+      height: 1px;
+    }
+    .inv-type::before {
+      bottom: -10px;
+    }
+    .inv-type::after {
+      bottom: -15px;
+    }
+    .inv-msg {
+      position: absolute;
+      right: 100px;
+      top: 0px;
+      font-size: 13px;
+      text-align: left;
+      color: var(--inv-color, #13509c);
+    }
+    .ant-select {
+      width: 390px;
+      border: none;
+      .ant-select-selection {
+        border: none;
+        box-shadow: none;
+        font-size: 25px;
+        text-align: center;
+        background-color: transparent;
+
+        .ant-select-selection-selected-value {
+          float: none;
+          text-align: center;
+          font-family: kaiti;
+          color: var(--inv-color, #13509c);
+        }
+        .ant-select-selection__placeholder {
+          text-align: center;
+          font-family: kaiti;
+          height: 30px;
+          line-height: 30px;
+          margin-top: -12px;
+        }
+      }
+    }
+    .ant-select::before, .ant-select::after {
+      content: '';
+      display: block;
+      width: 100%;
+      position: absolute;
+      border-top: var(--inv-color, #13509c) 1px solid;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+      height: 1px;
+    }
+    .ant-select::before {
+      bottom: -10px;
+    }
+    .ant-select::after {
+      bottom: -15px;
+    }
+    .date {
+      position: absolute;
+      right: 100px;
+      top: 5px;
+      color: var(--inv-color, #13509c);
+    }
+  }
+
+  .ant-input {
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    box-shadow: none!important;
+    height: 28px;
+    font-size: 13px;
+    background: transparent;
+  }
+  .ant-input:hover, .ant-input:active, .ant-input:focus {
+    border-color: var(--inv-color, #13509c)!important;
+  }
+  .ant-input.ant-input-disabled {
+    cursor: text;
+    color: rgba(0, 0, 0, 0.85);
+    background: transparent!important;
+  }
+
+  .ant-input-number {
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-radius: 0;
+    box-shadow: none!important;
+    height: 28px;
+    font-size: 13px;
+    .ant-input-number-handler-wrap {
+      display: none;
+    }
+  }
+  .ant-input-number:hover, .ant-input-number:active, .ant-input-number:focus {
+    border-color: var(--inv-color, #13509c)!important;
+  }
+
+  .inv-body {
+    border: var(--inv-color, #13509c) 1px solid;
+    font-size: 13px;
+    margin-right: 30px;
+
+    .inv-main-content {
+      display: flex;
+
+      .inv-buyer, .inv-notice {
+        width: 50%;
+        display: flex;
+        .inv-label {
+          color: var(--inv-color, #13509c);
+          width: 6.25%;
+          display: flex;
+          flex-direction: column;
+          writing-mode: vertical-rl;
+          justify-content: center;
+          align-items: center;
+          letter-spacing: 5px;
+          border-right: var(--inv-color, #13509c) 1px solid;
+        }
+        .inv-content {
+          flex: 1;
+          padding: 6px 0;
+
+          .mk-name .ant-input-affix-wrapper .ant-input-suffix {
+            right: 35px;
+          }
+
+          .ant-form-item {
+            display: flex;
+            padding: 0 5px 0 15px;
+            font-size: 13px;
+            margin-bottom: 5px;
+            
+            .ant-form-item-label {
+              line-height: 30px;
+              text-align: justify;
+              label {
+                display: flex;
+                color: var(--inv-color, #13509c);
+                span {
+                  display: inline-block;
+                  flex: 1;
+                }
+              }
+            }
+            .ant-form-item-control-wrapper {
+              width: 100%;
+
+              .ant-form-item-control {
+                line-height: 30px;
+                .ant-form-extra {
+                  position: absolute;
+                  top: 1px;
+                  right: 10px;
+                  font-size: 16px;
+                  .anticon {
+                    cursor: pointer;
+                  }
+                }
+                .ant-input-affix-wrapper:not(:hover) {
+                  .ant-input-suffix {
+                    opacity: 0;
+                  }
+                }
+              }
+            }
+          }
+          .ant-form-item.mutil-input {
+            .ant-form-item-children {
+              display: flex;
+            }
+          }
+        }
+      }
+      .inv-buyer {
+        border-right: var(--inv-color, #13509c) 1px solid;
+        .ant-form-item-label {
+          width: 103px;
+          min-width: 103px;
+          label:not(.ant-form-item-required) {
+            padding-left: 11px;
+          }
+          .ant-form-item-required::before {
+            line-height: 30px;
+          }
+        }
+      }
+      .inv-notice {
+        .inv-content {
+          padding-top: 45px;
+        }
+        .ant-form-item-label {
+          width: 75px;
+          min-width: 75px;
+        }
+      }
+    }
+
+    .inv-details {
+      border-top: var(--inv-color, #13509c) 1px solid;
+      border-bottom: var(--inv-color, #13509c) 1px solid;
+    }
+  }
+  .inv-tail {
+    display: flex;
+    padding-top: 10px;
+    margin-right: 30px;
+    .ant-form-item {
+      flex: 1;
+      display: flex;
+      font-size: 13px;
+      .ant-form-item-label, .ant-form-item-control-wrapper {
+        width: 40%;
+      }
+    }
+  }
+
+  .loading-mask {
+    position: absolute;
+    left: 0px;
+    top: 0;
+    right: 0px;
+    bottom: 0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: justify;
+    z-index: 1;
+
+    .ant-spin-blur {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      opacity: 0.5;
+      background: #ffffff;
+    }
+  }
+}
+.menu-invoice-wrap.read_only {
+  .ant-form-item-children {
+    color: rgba(0, 0, 0, 0.85);
+  }
+  .ant-input-suffix, .ant-form-extra, .anticon-ellipsis {
+    display: none;
+  }
+  .plus-line, .del-line {
+    display: none!important;
+  }
+}
+.inv-table {
+  .ant-table .ant-table-tbody {
+    td {
+      vertical-align: top;
+    }
+    tr:hover td {
+      background-color: var(--mk-sys-color1);
+    }
+  }
+}
+.tb-search-wrap {
+  .search-item {
+    display: flex;
+    float: left;
+    width: 350px;
+    align-items: center;
+    justify-content: flex-end;
+
+    .ant-input {
+      width: 200px;
+    }
+  }
+  .ant-btn {
+    margin-bottom: 20px;
+    margin-left: 50px;
+    background-color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    color: #ffffff;
+  }
+  .ant-btn:hover, .ant-btn:active {
+    background-color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    color: #ffffff;
+    opacity: 0.9;
+  }
+}
+
+.inv-type-select {
+  .ant-select-dropdown-menu-item {
+    text-align: center;
+  }
+}
+
diff --git a/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx b/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx
new file mode 100644
index 0000000..f9cbe0c
--- /dev/null
+++ b/src/tabviews/custom/components/module/invoice/invoiceTable/index.jsx
@@ -0,0 +1,474 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Input, InputNumber, notification, Modal } from 'antd'
+import { EllipsisOutlined } from '@ant-design/icons'
+
+import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
+import SubTable from '../subTable'
+import './index.scss'
+
+class DetailLine extends React.Component {
+  state = {
+    bill_count: 0,
+    unitprice: 0,
+    amount_line: 0,
+    visible: false
+  }
+
+  UNSAFE_componentWillMount() {
+    let { line } = this.props
+
+    this.setState({
+      bill_count: line.bill_count || '',
+      unitprice: line.unitprice || '',
+      amount_line: line.amount_line || ''
+    })
+  }
+
+  onChange = (value, key, nextkey) => {
+    let line = {...this.props.line}
+
+    if (['bill_count', 'unitprice', 'amount_line'].includes(key)) {
+      line[key] = value || 0
+      if (isNaN(line[key])) {
+        line[key] = 0
+      }
+      if (line[key]) {
+        if (key === 'bill_count') {
+          line[key] = Math.round(line[key] * 10000000000) / 10000000000
+          if (line.unitprice) {
+            line.amount_line = Math.round(line.unitprice * line.bill_count * 100) / 100
+          }
+        } else if (key === 'unitprice') {
+          line[key] = Math.round(line[key] * 10000000000) / 10000000000
+          if (line.bill_count) {
+            line.amount_line = Math.round(line.unitprice * line.bill_count * 100) / 100
+          }
+        } else if (key === 'amount_line') {
+          line[key] = Math.round(line[key] * 100) / 100
+          if (line.bill_count) {
+            line.unitprice = Math.round(line.amount_line / line.bill_count * 10000000000) / 10000000000
+          } else if (line.unitprice) {
+            line.bill_count = Math.round(line.amount_line / line.unitprice * 10000000000) / 10000000000
+          }
+        }
+      } else if (key === 'amount_line') {
+        line.bill_count = 0
+      }
+
+      if (line.amount_line) {
+        line.tax_amount = line.amount_line - line.amount_line / (line.tax_rate + 1)
+        line.tax_amount = Math.round(line.tax_amount * 100) / 100
+      } else {
+        line.tax_amount = 0
+      }
+    } else {
+      line[key] = value
+    }
+
+    this.setState({
+      bill_count: line.bill_count || '',
+      unitprice: line.unitprice || '',
+      amount_line: line.amount_line || ''
+    })
+
+    this.props.changeLine(line, key)
+
+    if (nextkey) {
+      let node = document.getElementById(nextkey)
+      if (node) {
+        if (node.select) {
+          node.select()
+        } else if (node.focus) {
+          node.focus()
+        }
+      }
+    }
+  }
+
+  onSkip = (key) => {
+    let node = document.getElementById(key)
+    if (node) {
+      if (node.select) {
+        node.select()
+      } else if (node.focus) {
+        node.focus()
+      }
+    }
+  }
+
+  render() {
+    const { line, delLine, trigger, field, pid } = this.props
+    const { bill_count, unitprice, amount_line } = this.state
+    
+    return <div className="mk-tr active">
+      <div className="mk-td">
+        <div className="mk-input">{line.productname || ''}<EllipsisOutlined onClick={trigger}/></div>
+      </div>
+      <div className="mk-td">
+        <Input defaultValue={line.spec || ''} autoFocus={field === 'spec'} onChange={(e) => this.onChange(e.target.value, 'spec')} onPressEnter={() => this.onSkip(pid + 'mk-invoice-unit')}/>
+      </div>
+      <div className="mk-td">
+        <Input id={pid + 'mk-invoice-unit'} defaultValue={line.unit || ''} autoFocus={field === 'unit'} onChange={(e) => this.onChange(e.target.value, 'unit')} onPressEnter={() => this.onSkip(pid + 'mk-invoice-billcount')}/>
+      </div>
+      <div className="mk-td">
+        <InputNumber id={pid + 'mk-invoice-billcount'} value={bill_count} autoFocus={field === 'bill_count'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({bill_count: val})} onPressEnter={() => this.onChange(bill_count, 'bill_count', pid + 'mk-invoice-unitprice')} onBlur={() => this.onChange(bill_count, 'bill_count')}/>
+      </div>
+      <div className="mk-td">
+        <InputNumber id={pid + 'mk-invoice-unitprice'} value={unitprice} autoFocus={field === 'unitprice'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({unitprice: val})} onPressEnter={() => this.onChange(unitprice, 'unitprice', pid + 'mk-invoice-amount')} onBlur={() => this.onChange(unitprice, 'unitprice')}/>
+      </div>
+      <div className="mk-td">
+        <InputNumber id={pid + 'mk-invoice-amount'} value={amount_line} autoFocus={field === 'amount_line'} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} onChange={(val) => this.setState({amount_line: val})} onPressEnter={() => this.onChange(amount_line, 'amount_line')} onBlur={() => this.onChange(amount_line, 'amount_line')}/>
+      </div>
+      <div className="mk-td mk-right">{line.tax_name}</div>
+      <div className="mk-td mk-right">{line.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} <span className="del-line" onClick={(e) => delLine(line.uuid, e)}></span> </div>
+    </div>
+  }
+}
+
+class InvoiceTable extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    timestamp: PropTypes.string,
+    read_only: PropTypes.any,
+    data: PropTypes.any,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    data: [],
+    editKey: '',
+    key: '',
+    total: {}
+  }
+
+  UNSAFE_componentWillMount () {
+    const { data } = this.props
+
+    let _data = fromJS(data).toJS()
+    if (!_data.length) {
+      _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}]
+    }
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.getTotal(_data)
+    })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('resetDetails', this.resetDetails)
+  }
+
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (this.props.timestamp !== nextProps.timestamp) {
+      let _data = fromJS(nextProps.data).toJS()
+      if (!_data.length) {
+        _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}]
+      }
+
+      this.setState({
+        data: _data
+      }, () => {
+        this.getTotal(_data)
+      })
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('resetDetails', this.resetDetails)
+  }
+  
+  changeMoneyToChinese = (money) => {
+    let cnNums = ['闆�', '澹�', '璐�', '鍙�', '鑲�', '浼�', '闄�', '鏌�', '鎹�', '鐜�']
+    let cnIntRadice = ['', '鎷�', '浣�', '浠�']
+    let cnIntUnits = ['', '涓�', '浜�', '鍏�']
+    let cnDecUnits = ['瑙�', '鍒�', '姣�', '鍘�']
+    let cnInteger = '鏁�'
+    let cnIntLast = '鍏�'
+    let maxNum = 999999999999999.9999 // 鏈�澶у鐞嗙殑鏁板瓧
+    let IntegerNum = null
+    let DecimalNum = null
+    let ChineseStr = ''
+    let parts = null // 鍒嗙閲戦鍚庣敤鐨勬暟缁勶紝棰勫畾涔�
+    let Symbol = ''  // 姝h礋鍊兼爣璁�
+
+    if (money === 0) return ''
+
+    if (money >= maxNum) return '瓒呭嚭鏈�澶у鐞嗘暟瀛�'
+
+    if(money < 0) {
+      money = -money
+      Symbol = '璐�'       
+    }
+    money = money.toString() // 杞崲涓哄瓧绗︿覆
+    if (money.indexOf('.') === -1) {
+      IntegerNum = money
+      DecimalNum = ''
+    } else {
+      parts = money.split('.')
+      IntegerNum = parts[0]
+      DecimalNum = parts[1].substr(0, 4)
+    }
+
+    if (parseInt(IntegerNum, 10) > 0) { // 鑾峰彇鏁村瀷閮ㄥ垎杞崲
+      let zeroCount = 0
+      let IntLen = IntegerNum.length
+      for (let i = 0; i < IntLen; i++) {
+        let n = IntegerNum.substr(i, 1)
+        let p = IntLen - i - 1
+        let q = p / 4
+        let m = p % 4
+        
+        if (n === '0') {
+          zeroCount++
+        } else {
+          if (zeroCount > 0) {
+            ChineseStr += cnNums[0]
+          }
+          zeroCount = 0 // 褰掗浂
+          ChineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
+        }
+
+        if (m === 0 && zeroCount < 4) {
+          ChineseStr += cnIntUnits[q]
+        }
+      }
+      ChineseStr += cnIntLast
+    }
+
+    if (DecimalNum !== '') { // 灏忔暟閮ㄥ垎
+      let decLen = DecimalNum.length
+
+      for (let i = 0; i < decLen; i++) {
+        let n = DecimalNum.substr(i, 1)
+        if (n !== '0') {
+          ChineseStr += cnNums[Number(n)] + cnDecUnits[i]
+        }
+      }
+    }
+    if (ChineseStr === '') {
+      ChineseStr += cnNums[0] + cnIntLast + cnInteger
+    } else if (DecimalNum === '') {
+      ChineseStr += cnInteger
+    }
+
+    ChineseStr = Symbol + ChineseStr
+    
+    return ChineseStr
+  }
+
+  getTotal = (data) => {
+    let price = 0
+    let tax = 0
+
+    data.forEach(item => {
+      if (!item.productcode) return
+
+      price += item.amount_line * 100
+      tax += item.tax_amount * 100
+    })
+
+    price = price / 100
+    tax = tax / 100
+
+    this.setState({total: {price, tax, sum: price, sumName: this.changeMoneyToChinese(price)}})
+  }
+
+  resetDetails = (data) => {
+    let _data = fromJS(data).toJS()
+
+    if (!_data.length) {
+      _data = [{uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}]
+    }
+
+    this.setState({data: _data}, () => {
+      this.getTotal(_data)
+    })
+  }
+
+  addLine = () => {
+    const { data } = this.state
+
+    let line = {uuid: Utils.getguid(), productname: '', spec: '', unit: '', bill_count: '', unitprice: 0, amount_line: 0, tax_rate: '', tax_name: '', tax_amount: 0}
+
+    this.setState({data: [...data, line]})
+  }
+
+  delLine = (uuid, e) => {
+    const { data } = this.state
+
+    e.stopPropagation()
+    
+    if (data.length === 1) {
+      notification.warning({
+        top: 92,
+        message: '鑷冲皯淇濈暀涓�琛屾槑缁嗭紒',
+        duration: 3
+      })
+      return
+    }
+
+    let _data = data.filter(item => item.uuid !== uuid)
+
+    this.setState({data: _data}, () => {
+      this.getTotal(_data)
+    })
+    this.props.onChange(_data)
+  }
+
+  changeLine = (record) => {
+    const { editKey, data } = this.state
+
+    let _data = data.map(item => {
+      if (item.uuid === editKey) {
+        return record
+      } else {
+        return item
+      }
+    })
+
+
+    this.setState({data: _data}, () => {
+      this.getTotal(_data)
+    })
+    this.props.onChange(_data)
+  }
+
+  checkLine = (uuid, key, e) => {
+    const { read_only } = this.props
+
+    e && e.stopPropagation()
+
+    if (read_only) return
+    
+    this.setState({editKey: uuid, key: key || ''}, () => {
+      if (key === 'productname') {
+        this.setState({visible: true})
+      }
+    })
+  }
+
+  changeDetail = (prod) => {
+    const { editKey, data } = this.state
+
+    let _data = data.map(item => {
+      if (item.uuid === editKey) {
+        item.productname = prod.productname
+        item.spec = prod.spec
+        item.unit = prod.unit
+        item.unitprice = prod.unitprice
+        item.tax_rate = prod.tax_rate || 0
+        item.tax_name = prod.tax_rate * 100 + '%'
+        item.free_tax_mark = prod.free_tax_mark || ''
+        item.vat_special_management = prod.vat_special_management || ''
+        item.tax_item = prod.tax_item || ''
+        item.tax_method = prod.tax_method || ''
+
+        if (prod.vat_special_management && prod.free_tax_mark === 'true') {
+          item.tax_name = prod.vat_special_management
+        }
+
+        item.productcode = prod.productcode
+        item.Description = prod.Description
+        item.tax_classify_code = prod.tax_classify_code
+        item.tax_classify_name = prod.tax_classify_name
+
+        if (item.bill_count && item.unitprice) {
+          item.amount_line = Math.round(item.unitprice * item.bill_count * 100) / 100
+        }
+        if (item.amount_line) {
+          item.tax_amount = item.amount_line - item.amount_line / (item.tax_rate + 1)
+          item.tax_amount = Math.round(item.tax_amount * 100) / 100
+        } else {
+          item.tax_amount = 0
+        }
+      }
+
+      return item
+    })
+
+    this.setState({data: _data, editKey: '', visible: false}, () => {
+      this.setState({editKey: editKey})
+      this.getTotal(_data)
+    })
+    this.props.onChange(_data)
+  }
+
+  render() {
+    const { config, tax_type } = this.props
+    const { editKey, key, data, total, visible } = this.state
+
+    return (
+      <div className="detail-wrap">
+        <span className="plus-line" onClick={this.addLine}></span>
+        <div className="mk-th">
+          <div className="mk-td">璐х墿鎴栧簲绋庡姵鍔°�佹湇鍔″悕绉�</div>
+          <div className="mk-td">瑙勬牸鍨嬪彿</div>
+          <div className="mk-td">鍗曚綅</div>
+          <div className="mk-td">鏁伴噺</div>
+          <div className="mk-td">鍗曚环锛堝惈绋庯級</div>
+          <div className="mk-td">閲戦锛堝惈绋庯級</div>
+          <div className="mk-td">绋庣巼</div>
+          <div className="mk-td">绋庨</div>
+        </div>
+        {data.map(item => {
+          if (editKey === item.uuid) {
+            return <DetailLine key={item.uuid} pid={config.uuid} line={item} field={key} changeLine={this.changeLine} delLine={this.delLine} trigger={() => this.setState({visible: true})}/>
+          }
+
+          return <div className="mk-tr" key={item.uuid} onClick={() => this.checkLine(item.uuid)}>
+            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, item.productname ? '' : 'productname', e)}>{item.productname || ''}</div>
+            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'spec', e)}>{item.spec || ''}</div>
+            <div className="mk-td mk-left" onClick={(e) => this.checkLine(item.uuid, 'unit', e)}>{item.unit || ''}</div>
+            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'bill_count', e)}>{`${item.bill_count || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'unitprice', e)}>{`${item.unitprice || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+            <div className="mk-td mk-right" onClick={(e) => this.checkLine(item.uuid, 'amount_line', e)}>{`${item.amount_line || ''}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+            <div className="mk-td mk-right">{item.tax_name}</div>
+            <div className="mk-td mk-right">{item.tax_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}<span className="del-line" onClick={(e) => this.delLine(item.uuid, e)}></span></div>
+          </div>
+        })}
+        <div className="mk-total">
+          <div className="mk-td">鍚堣</div>
+          <div className="mk-td"></div>
+          <div className="mk-td"></div>
+          <div className="mk-td"></div>
+          <div className="mk-td"></div>
+          <div className="mk-td">锟`${total.price}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+          <div className="mk-td"></div>
+          <div className="mk-td">锟`${total.tax}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+        </div>
+        <div className="mk-upcase">
+          <div className="mk-td">浠风◣鍚堣锛堝ぇ鍐欙級</div>
+          <div className="mk-td">{total.sumName}</div>
+          <div className="mk-td">锛堝皬鍐欙級锟`${total.sum}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}</div>
+        </div>
+        <Modal
+          title="鍟嗗搧淇℃伅"
+          visible={visible}
+          width="75vw"
+          maskClosable={false}
+          onCancel={() => { this.setState({ visible: false }) }}
+          footer={null}
+        >
+          <SubTable config={config} tax_type={tax_type} onChange={this.changeDetail}/>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default InvoiceTable
\ No newline at end of file
diff --git a/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss b/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss
new file mode 100644
index 0000000..2621d4a
--- /dev/null
+++ b/src/tabviews/custom/components/module/invoice/invoiceTable/index.scss
@@ -0,0 +1,131 @@
+.detail-wrap {
+  position: relative;
+
+  .plus-line, .del-line {
+    position: absolute;
+    right: -40px;
+    top: 5px;
+    font-size: 26px;
+    border: 1px solid var(--inv-color, #13509c);
+    width: 30px;
+    height: 30px;
+    transition: all 0.3s;
+    cursor: pointer;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+  .plus-line::before, .del-line::before {
+    content: ' ';
+    position: absolute;
+    top: 13px;
+    width: 12px;
+    height: 1px;
+    background: var(--inv-color, #13509c);
+    transition: all 0.3s;
+  }
+  .plus-line::after {
+    content: ' ';
+    position: absolute;
+    top: 13px;
+    width: 12px;
+    height: 1px;
+    background: var(--inv-color, #13509c);
+    transform: rotate(90deg);
+    transition: all 0.3s;
+  }
+
+  .del-line {
+    display: none;
+  }
+  .mk-tr:hover {
+    .del-line {
+      display: flex;
+    }
+    .del-line::after {
+      content: ' ';
+      position: absolute;
+      top: -6px;
+      width: 12px;
+      height: 40px;
+      left: -12px;
+    }
+  }
+
+  .mk-th, .mk-tr, .mk-total {
+    position: relative;
+    display: flex;
+    border-bottom: var(--inv-color, #13509c) 1px solid;
+
+    .mk-td {
+      width: 10%;
+      height: 40px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      padding: 0 5px;
+    }
+    .mk-td:not(:last-child) {
+      border-right: var(--inv-color, #13509c) 1px solid;
+    }
+    .mk-td:first-child {
+      width: 20%;
+    }
+    .mk-td:nth-child(2), .mk-td:nth-child(6) {
+      width: 15%;
+    }
+
+    .mk-left {
+      justify-content: start;
+    }
+    .mk-right {
+      justify-content: end;
+    }
+
+    .mk-input {
+      position: relative;
+      height: 28px;
+      width: 100%;
+      background: #ffffff;
+      border-bottom: 1px solid #d9d9d9;
+      transition: all 0.3s;
+
+      .anticon-ellipsis {
+        position: absolute;
+        right: 0px;
+        padding: 5px 10px;
+        cursor: pointer;
+      }
+    }
+    .mk-input:hover {
+      border-color: var(--inv-color, #13509c);
+    }
+
+    .ant-input {
+      background: #ffffff;
+    }
+  }
+  .mk-tr.active, .mk-tr:hover {
+    background: var(--mk-sys-color1);
+  }
+  .mk-upcase {
+    display: flex;
+
+    .mk-td {
+      width: 40%;
+      height: 40px;
+      display: flex;
+      align-items: center;
+      padding: 0 20px;
+    }
+    .mk-td:first-child {
+      width: 20%;
+      padding: 0;
+      border-right: var(--inv-color, #13509c) 1px solid;
+      justify-content: center;
+    }
+    .mk-td:last-child {
+      justify-content: end;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/custom/components/module/invoice/subTable/index.jsx b/src/tabviews/custom/components/module/invoice/subTable/index.jsx
new file mode 100644
index 0000000..6b966e7
--- /dev/null
+++ b/src/tabviews/custom/components/module/invoice/subTable/index.jsx
@@ -0,0 +1,250 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Table, Input, Button } from 'antd'
+
+import Api from '@/api'
+import UtilsDM from '@/utils/utils-datamanage.js'
+// import './index.scss'
+
+class SearchWrap extends Component {
+  static propTpyes = {
+    search: PropTypes.array,
+    onChange: PropTypes.func
+  }
+
+  state = {
+    search: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { search } = this.props
+
+    this.setState({
+      search: fromJS(search).toJS()
+    })
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  searchChange = (val, key) => {
+    const { search } = this.state
+
+    this.setState({search: search.map(item => {
+      if (item.field === key) {
+        item.value = val
+      }
+      return item
+    })})
+  }
+
+  trigger = () => {
+    const { search } = this.state
+
+    this.props.onChange(search)
+  }
+
+  render() {
+    const { search } = this.state
+
+    return (
+      <div className="tb-search-wrap">
+        {search.map(item => (
+          <div className="search-item" key={item.field}>
+            {item.label}锛�
+            <Input autoComplete="off" onChange={(e) => this.searchChange(e.target.value, item.field)}/>
+          </div>
+        ))}
+        <Button onClick={this.trigger}>鎼滅储</Button>
+      </div>
+    )
+  }
+}
+
+class SubTable extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {
+    pageIndex: 1,         // 鍒濆椤甸潰绱㈠紩
+    pageSize: 10,         // 姣忛〉鏁版嵁鏉℃暟
+    columns: null,        // 鏄剧ず鍒�
+    pageOptions: [],
+    search: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    let _columns = []
+
+    config.columns.forEach(item => {
+      if (item.Hide === 'true') return
+      _columns.push({
+        align: 'left',
+        dataIndex: item.field,
+        title: item.label,
+        sorter: false,
+        width: item.Width || 120
+      })
+    })
+
+    let size = (config.setting.pageSize || 10) + ''
+    let pageOptions = ['10', '25', '50', '100', '500', '1000']
+
+    if (!pageOptions.includes(size)) {
+      pageOptions.push(size)
+      pageOptions = pageOptions.sort((a, b) => a - b)
+    }
+
+    this.setState({
+      pageSize: config.pageSize || 10,
+      pageOptions,
+      search: fromJS(config.search).toJS(),
+      columns: _columns
+    })
+  }
+
+  componentDidMount() {
+    const { config } = this.props
+
+    if (config.setting.onload === 'true') {
+      this.loadData()
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  /**
+   * @description 鏁版嵁鍔犺浇
+   */
+  async loadData () {
+    const { config, tax_type } = this.props
+    const { search, pageIndex, pageSize } = this.state
+
+    this.setState({
+      loading: true
+    })
+
+    let searches = search.map(item => ({
+      key: item.field,
+      match: item.match,
+      type: item.type,
+      value: item.value || ''
+    }))
+
+    let param = UtilsDM.getQueryDataParams(config.setting, searches, config.setting.order, pageIndex, pageSize, '')
+
+    this.requestId = config.uuid + new Date().getTime()
+
+    let result = await Api.genericInterface(param, config.setting.js_script, '', this.requestId)
+
+    if (result.status) {
+      if (result.$requestId && this.requestId !== result.$requestId) return
+
+      let start = pageSize * (pageIndex - 1) + 1
+
+      let data = result.data.map((item, index) => {
+        item.key = index
+        item.$Index = start + index + ''
+
+        if (tax_type) {
+          item.tax_rate = tax_type === 'special_invoice' ? item.general_tax_rate : item.small_tax_rate
+          item.tax_rate = isNaN(item.tax_rate) ? 0 : +item.tax_rate
+        }
+
+        return item
+      })
+
+      let total = result.total || 0
+      if (config.setting.custompage && data.length) {
+        total = data[data.length - 1].mk_total || 0
+      }
+
+      this.setState({
+        data: data,
+        total: total,
+        loading: false
+      })
+
+      UtilsDM.querySuccess(result)
+    } else {
+      this.setState({
+        loading: false
+      })
+      
+      UtilsDM.queryFail(result)
+    }
+  }
+
+  changeTable = (pagination) => {
+    this.setState({
+      pageIndex: pagination.current,
+      pageSize: pagination.pageSize,
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  doubleClickLine = (record) => {
+    this.props.onChange(record)
+  }
+
+  searchChange = (search) => {
+    this.setState({search: search}, () => {
+      this.loadData()
+    })
+  }
+
+  render() {
+    const { pageIndex, pageSize, pageOptions, columns, total, loading, data, search } = this.state
+
+    return (
+      <>
+        <SearchWrap search={search} onChange={this.searchChange}/>
+        <Table
+          className="inv-table"
+          columns={columns}
+          dataSource={data}
+          bordered={true}
+          loading={loading}
+          onRow={(record) => {
+            return {
+              onDoubleClick: () => {this.doubleClickLine(record)}
+            }
+          }}
+          onChange={this.changeTable}
+          pagination={{
+            current: pageIndex,
+            pageSize: pageSize,
+            pageSizeOptions: pageOptions,
+            showSizeChanger: true,
+            total: total || 0,
+            showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+          }}
+        />
+      </>
+    )
+  }
+}
+
+export default SubTable
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/tabviews/custom/components/module/invoice/subTable/index.scss
similarity index 100%
copy from src/tabviews/zshare/actionList/shareLink/index.scss
copy to src/tabviews/custom/components/module/invoice/subTable/index.scss
diff --git a/src/tabviews/custom/components/module/voucher/index.jsx b/src/tabviews/custom/components/module/voucher/index.jsx
index 8c282b4..0fd7ac5 100644
--- a/src/tabviews/custom/components/module/voucher/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/index.jsx
@@ -12,10 +12,8 @@
 import ResetRemark from './resetRemark'
 import ResetAttach from './resetAttach'
 import LoadFromTemp from './loadFromTemp'
-import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
-const PrintVoucher = asyncComponent(() => import('./printVoucher'))
 const { confirm } = Modal
 
 class VoucherModule extends Component {
@@ -39,6 +37,8 @@
     username: sessionStorage.getItem('User_Name'),
     remark: '',
     attachments: 0,
+    vouAduited: false,
+    vouReadOnly: false,
     attachlist: [],
     oriAttachs: [],
     tempTypes: [],
@@ -304,6 +304,7 @@
 
       let data = []
       if (res.voucher) {
+        let disabled = res.voucher_status === 'true'
         data = res.voucher.map(line => {
           line.uuid = line.subject_id || ''
 
@@ -320,6 +321,7 @@
           line.exratename = line.foreign_exratename || ''
           line.local_currency = line.local_exratecode || ''
           line.foreign_currency_type = line.foreign_type || ''
+          line.$disabled = disabled
 
           if (line.sup) {
             line.supAccounts = line.sup.map(cell => {
@@ -351,7 +353,9 @@
           data: data,
           attachlist: files,
           vouDate: res.fibvoucherdate ? moment(res.fibvoucherdate, 'YYYY-MM-DD') : null,
-          charType: res.voucher_class,
+          charType: res.voucher_class || 'keeping',
+          vouAduited: res.voucher_status === 'true' || res.read_only === 'true',
+          vouReadOnly: res.read_only === 'true',
           charName: res.voucher_char,
           charInt: res.voucher_char_int,
           // orgcode: res.orgcode,
@@ -1059,10 +1063,6 @@
     this.setState({status: 'change', attachlist: vals, attachments: num})
   }
 
-  triggermore = () => {
-
-  }
-
   triggerclose = () => {
     const { config, status } = this.state
 
@@ -1139,72 +1139,233 @@
     })
   }
 
-  render() {
-    const { type, status, loading, config, orgcode, orgname, typeOptions, tempTypes, charType, charName, charInt, data, vouDate, username, remark, attachments, title, attachlist, tempTypeClass } = this.state
+  triggerPrint = () => {
+    const { config, BID } = this.state
 
-    return (
-      <div className="menu-voucher-wrap" style={config.style}>
-        {type === 'createVoucher' ? <div className="voucher-header">
-          <Button className="add-background header-btn" disabled={status === 'empty'} onClick={() => this.triggersave('add')}>淇濆瓨骞舵柊澧�</Button>
-          <Button className="add-background header-btn" disabled={status === 'empty' || status === 'saved'} onClick={() => this.triggersave()}>淇濆瓨</Button>
-          <PrintVoucher ID={config.uuid + 'print'} data={data} orgname={orgname} vouDate={vouDate} charName={charName} charInt={charInt} attachments={attachments} disabled={status !== 'saved'}/>
-          <Dropdown overlay={<div className="mk-voucher-dropdown-wrap">
-            <SaveAsTemp tempTypes={tempTypes} onChange={this.triggerTempsave}/>
-            <div className="split"></div>
-            <LoadFromTemp tempTypes={tempTypes} onChange={this.triggerTempLoad}/>
-          </div>} trigger={['click']}>
-            <Button className="out-background header-btn" onClick={this.triggermore}>鏇村</Button>
-          </Dropdown>
-        </div> : null}
-        {type === 'checkVoucher' ? <div className="voucher-header">
-          <Button className="add-background header-btn" disabled={status === 'empty' || status === 'saved'} onClick={() => this.triggersave()}>淇濆瓨</Button>
-          <PrintVoucher ID={config.uuid + 'print'} data={data} orgname={orgname} vouDate={vouDate} charName={charName} charInt={charInt} attachments={attachments} disabled={status !== 'saved'}/>
-          <Button className="out-background header-btn" onClick={this.triggerclose}>鍏抽棴</Button>
-        </div> : null}
-        <div className="voucher-body" style={{padding: `0px ${config.wrap.space || 0}px`}}>
-          {type === 'createVoucher' || type === 'checkVoucher' ? <div className="pre-wrap">
-            <div className="voucher-code">
-              <Select value={charType} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({status: 'change', charType: val, charName: option.props.charName, charInt: option.props.charint})}>
-                {typeOptions.map(option =>
-                  <Select.Option key={option.id} value={option.voucher_class} charName={option.voucher_char} charint={option.voucher_char_int}>{option.voucher_char}</Select.Option>
-                )}
-              </Select>
-              <InputNumber precision={0} min={1} value={charInt} autoComplete="off" onChange={(val) => this.setState({status: 'change', charInt: val})}/> 鍙�
+    if (!config.wrap.printTemp) {
+      notification.warning({
+        top: 92,
+        message: '灏氭湭璁剧疆鎵撳嵃妯℃澘锛�',
+        duration: 5
+      })
+      return
+    }
+
+    window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: BID, tempId: config.wrap.printTemp, pageId: config.$pageId || '', dataM: sessionStorage.getItem('dataM') }))))
+  }
+
+  triggerAduit = () => {
+    const { book, BID, voucherCode, username } = this.state
+
+    if (!book) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨璐﹀锛�',
+        duration: 5
+      })
+      return
+    }
+
+    let param = {
+      func: 's_fcc_voucher_sub',
+      ID: BID,
+      status: 10,
+      statusname: '宸插鏍�',
+      voucher_code: voucherCode || '',
+      username: username,
+      fullname: sessionStorage.getItem('Full_Name') || ''
+    }
+
+    const that = this
+
+    confirm({
+      content: '纭畾瑕佸鏍稿悧锛�',
+      onOk() {
+        Api.genericInterface(param).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            return
+          }
+    
+          notification.success({
+            top: 92,
+            message: '宸茬粡閫氳繃瀹℃牳',
+            duration: 2
+          })
+
+          that.getVoucher()
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  triggerUnAduit = () => {
+    const { book, BID, voucherCode, username } = this.state
+
+    if (!book) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨璐﹀锛�',
+        duration: 5
+      })
+      return
+    }
+
+    let param = {
+      func: 's_fcc_voucher_sub',
+      ID: BID,
+      status: 0,
+      statusname: '鍙栨秷瀹℃牳',
+      voucher_code: voucherCode || '',
+      username: username,
+      fullname: sessionStorage.getItem('Full_Name') || ''
+    }
+
+    const that = this
+
+    confirm({
+      content: '纭瑕佸彇娑堝鏍稿悧锛�',
+      onOk() {
+        Api.genericInterface(param).then(res => {
+          if (!res.status) {
+            notification.warning({
+              top: 92,
+              message: res.message,
+              duration: 5
+            })
+            return
+          }
+
+          notification.success({
+            top: 92,
+            message: '瀹℃牳宸插彇娑�',
+            duration: 2
+          })
+
+          that.getVoucher()
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  render() {
+    const { type, status, loading, config, orgcode, typeOptions, tempTypes, charType, charInt, data, vouDate, username, remark, attachments, title, attachlist, tempTypeClass, vouAduited, vouReadOnly, voucherCode } = this.state
+
+    if (type === 'checkVoucher') {
+      return (
+        <div className="menu-voucher-wrap" style={config.style}>
+          <div className="voucher-header" style={{padding: `10px ${config.wrap.space || 0}px`}}>
+            {!vouAduited ? <Button disabled={status === 'empty' || status === 'saved'} onClick={() => this.triggersave()}>淇濆瓨</Button> : null}
+            {/* <PrintVoucher ID={config.uuid + 'print'} data={data} orgname={orgname} vouDate={vouDate} charName={charName} charInt={charInt} attachments={attachments} disabled={status !== 'saved'}/> */}
+            <Button disabled={status !== 'saved'} onClick={this.triggerPrint}>鎵撳嵃</Button>
+            {vouAduited && !vouReadOnly ? <Button onClick={this.triggerUnAduit}>鍙栨秷瀹℃牳</Button> : null}
+            {!vouAduited && !vouReadOnly ? <Button onClick={this.triggerAduit}>瀹℃牳</Button> : null}
+            <Button onClick={this.triggerclose}>鍏抽棴</Button>
+          </div>
+          <div className="voucher-body" style={{padding: `0px ${config.wrap.space || 0}px`}}>
+            <div className="pre-wrap">
+              <div className="voucher-number">
+                鍑瘉鍙凤細{voucherCode}
+              </div>
+              <div className="voucher-code">
+                <Select value={charType} disabled={vouAduited} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({status: 'change', charType: val, charName: option.props.charname, charInt: option.props.charint})}>
+                  {typeOptions.map(option =>
+                    <Select.Option key={option.id} value={option.voucher_class} charname={option.voucher_char} charint={option.voucher_char_int}>{option.voucher_char}</Select.Option>
+                  )}
+                </Select>
+                <InputNumber precision={0} min={1} disabled={vouAduited} value={charInt} autoComplete="off" onChange={(val) => this.setState({status: 'change', charInt: val})}/> 鍙�
+              </div>
+              <div className="voucher-date">
+                鏃ユ湡锛�<DatePicker value={vouDate} disabled={vouAduited} onChange={this.changeVouDate}/>
+              </div>
+              <div className="voucher-text">
+                <Input value={title} placeholder={vouAduited ? '' : '鍑瘉鏂囨湰'} disabled={vouAduited} autoComplete="off" onChange={(e) => this.setState({status: 'change', title: e.target.value})}/>
+              </div>
+              <div className="voucher-affix">
+                闄勫崟鎹� <InputNumber precision={0} disabled={vouAduited} value={attachments || 0} autoComplete="off" onChange={this.changeAttach}/> 寮�
+                <ResetAttach config={config} disabled={vouAduited} orgcode={orgcode} voucherCode={this.state.voucherCode} attachlist={attachlist} onChange={this.resetAttachList}/>
+                <ResetRemark remark={remark} disabled={vouAduited} ID={config.uuid + 'remark'} onChange={(val) => this.setState({status: 'change', remark: val})}/>
+              </div>
             </div>
-            <div className="voucher-date">
-              鏃ユ湡锛�<DatePicker value={vouDate} onChange={this.changeVouDate}/>
-            </div>
-            <div className="voucher-text">
-              <Input value={title} placeholder="鍑瘉鏂囨湰" autoComplete="off" onChange={(e) => this.setState({status: 'change', title: e.target.value})}/>
-            </div>
-            <div className="voucher-affix">
-              闄勫崟鎹� <InputNumber precision={0} value={attachments || 0} autoComplete="off" onChange={this.changeAttach}/> 寮�
-              <ResetAttach config={config} orgcode={orgcode} voucherCode={this.state.voucherCode} attachlist={attachlist} onChange={this.resetAttachList}/>
-              <ResetRemark remark={remark} ID={config.uuid + 'remark'} onChange={(val) => this.setState({status: 'change', remark: val})}/>
-            </div>
-          </div> : null}
-          {type === 'createTemp' || type === 'checkTemp' ? <div className="pre-temp-wrap">
-            <div className="temp-text">
-              <span>妯℃澘鍚嶇О锛�</span><Input value={title} placeholder="妯℃澘鍚嶇О" autoComplete="off" onChange={(e) => this.setState({title: e.target.value})}/>
-            </div>
-            <div className="temp-text">
-              <span>妯℃澘绫诲瀷锛�</span>
-              <Select value={tempTypeClass} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({tempTypeClass: val, tempTypeName: option.props.children})}>
-                {tempTypes.map(option =>
-                  <Select.Option key={option.data_code} value={option.data_code}>{option.data_name}</Select.Option>
-                )}
-              </Select>
-            </div>
-            <div className="temp-action">
-              <Button className="save-temp header-btn" onClick={() => this.triggerTempsave()}>淇濆瓨</Button>
-              <Button className="close-temp header-btn" onClick={this.triggerclose}>鍏抽棴</Button>
-            </div>
-          </div> : null}
-          <VoucherTable config={config} loading={loading} data={data} onChange={this.dataChange}/>
+            <VoucherTable config={config} loading={loading} data={data} onChange={this.dataChange}/>
+          </div>
+          <div className="user" style={{paddingLeft: `${config.wrap.space || 0}px`}}>鍒跺崟浜猴細{username}</div>
         </div>
-        {type === 'createVoucher' || type === 'checkVoucher' ? <div className="user">鍒跺崟浜猴細{username}</div> : null}
-      </div>
-    )
+      )
+    } else if (type === 'createVoucher') {
+      return (
+        <div className="menu-voucher-wrap" style={config.style}>
+          <div className="voucher-header" style={{padding: `10px ${config.wrap.space || 0}px`}}>
+            <Button disabled={status === 'empty'} onClick={() => this.triggersave('add')}>淇濆瓨骞舵柊澧�</Button>
+            <Button disabled={status === 'empty' || status === 'saved'} onClick={() => this.triggersave()}>淇濆瓨</Button>
+            <Button disabled={status !== 'saved'} onClick={this.triggerPrint}>鎵撳嵃</Button>
+            <Dropdown overlay={<div className="mk-voucher-dropdown-wrap">
+              <SaveAsTemp tempTypes={tempTypes} onChange={this.triggerTempsave}/>
+              <div className="split"></div>
+              <LoadFromTemp tempTypes={tempTypes} onChange={this.triggerTempLoad}/>
+            </div>} trigger={['hover']} placement="bottomCenter">
+              <Button>鏇村</Button>
+            </Dropdown>
+          </div>
+          <div className="voucher-body" style={{padding: `0px ${config.wrap.space || 0}px`}}>
+            <div className="pre-wrap">
+              <div className="voucher-code">
+                <Select value={charType} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({status: 'change', charType: val, charName: option.props.charname, charInt: option.props.charint})}>
+                  {typeOptions.map(option =>
+                    <Select.Option key={option.id} value={option.voucher_class} charname={option.voucher_char} charint={option.voucher_char_int}>{option.voucher_char}</Select.Option>
+                  )}
+                </Select>
+                <InputNumber precision={0} min={1} value={charInt} autoComplete="off" onChange={(val) => this.setState({status: 'change', charInt: val})}/> 鍙�
+              </div>
+              <div className="voucher-date">
+                鏃ユ湡锛�<DatePicker value={vouDate} onChange={this.changeVouDate}/>
+              </div>
+              <div className="voucher-text">
+                <Input value={title} placeholder="鍑瘉鏂囨湰" autoComplete="off" onChange={(e) => this.setState({status: 'change', title: e.target.value})}/>
+              </div>
+              <div className="voucher-affix">
+                闄勫崟鎹� <InputNumber precision={0} value={attachments || 0} autoComplete="off" onChange={this.changeAttach}/> 寮�
+                <ResetAttach config={config} orgcode={orgcode} voucherCode={this.state.voucherCode} attachlist={attachlist} onChange={this.resetAttachList}/>
+                <ResetRemark remark={remark} ID={config.uuid + 'remark'} onChange={(val) => this.setState({status: 'change', remark: val})}/>
+              </div>
+            </div>
+            <VoucherTable config={config} loading={loading} data={data} onChange={this.dataChange}/>
+          </div>
+          <div className="user" style={{paddingLeft: `${config.wrap.space || 0}px`}}>鍒跺崟浜猴細{username}</div>
+        </div>
+      )
+    } else {
+      return (
+        <div className="menu-voucher-wrap" style={config.style}>
+          <div className="voucher-body" style={{padding: `0px ${config.wrap.space || 0}px`}}>
+            <div className="pre-temp-wrap">
+              <div className="temp-text">
+                <span>妯℃澘鍚嶇О锛�</span><Input value={title} placeholder="妯℃澘鍚嶇О" autoComplete="off" onChange={(e) => this.setState({title: e.target.value})}/>
+              </div>
+              <div className="temp-text">
+                <span>妯℃澘绫诲瀷锛�</span>
+                <Select value={tempTypeClass} dropdownClassName="mk-vcode-dropdown" onChange={(val, option) => this.setState({tempTypeClass: val, tempTypeName: option.props.children})}>
+                  {tempTypes.map(option =>
+                    <Select.Option key={option.data_code} value={option.data_code}>{option.data_name}</Select.Option>
+                  )}
+                </Select>
+              </div>
+              <div className="temp-action">
+                <Button onClick={() => this.triggerTempsave()}>淇濆瓨</Button>
+                <Button onClick={this.triggerclose}>鍏抽棴</Button>
+              </div>
+            </div>
+            <VoucherTable config={config} loading={loading} data={data} onChange={this.dataChange}/>
+          </div>
+        </div>
+      )
+    }
   }
 }
 
diff --git a/src/tabviews/custom/components/module/voucher/index.scss b/src/tabviews/custom/components/module/voucher/index.scss
index 4eec234..b3e1c34 100644
--- a/src/tabviews/custom/components/module/voucher/index.scss
+++ b/src/tabviews/custom/components/module/voucher/index.scss
@@ -14,13 +14,31 @@
     padding: 10px;
     border-bottom: 1px solid #eeeeee;
 
-    .header-btn {
+    .ant-btn {
       height: 28px;
       min-width: 80px;
       margin-right: 10px;
+      background-color: #ffffff;
+      border-color: #d8d8d8;
+      color: rgba(0, 0, 0, 0.65);
+    }
+    .ant-btn[disabled] {
+      background-color: #dadada!important;
+      border-color: #dadada!important;
+      color: #ffffff!important;
+    }
+    .ant-btn:not([disabled]):hover {
+      background-color: var(--mk-sys-color);
+      border-color: var(--mk-sys-color);
+      color: #ffffff;
     }
   }
   .voucher-body {
+    .voucher-number {
+      display: inline-block;
+      white-space: nowrap;
+      margin-right: 15px;
+    }
     .voucher-code {
       display: inline-block;
       width: 160px;
@@ -52,6 +70,10 @@
     }
     .pre-wrap {
       padding: 10px 0px;
+
+      .ant-input.ant-input-disabled, .ant-input-number.ant-input-number-disabled, .ant-select.ant-select-disabled {
+        color: rgba(0, 0, 0, 0.65);
+      }
     }
     .voucher-date {
       display: inline-block;
@@ -61,7 +83,7 @@
     }
     .voucher-text {
       display: inline-block;
-      width: calc(56% - 350px);
+      width: calc(68% - 545px);
       margin-left: 12px;
     }
     .voucher-affix {
@@ -91,42 +113,14 @@
         .ant-btn {
           margin-left: 15px;
         }
+        .ant-btn:hover {
+          color: var(--mk-sys-color);
+          border-color: var(--mk-sys-color);
+        }
       }
     }
   }
 
-  .add-background {
-    background: #26C281;
-    border-color: #26C281;
-    color: #ffffff;
-  }
-  .print-background {
-    background-color: #8E44AD;
-    border-color: #8E44AD;
-    color: #ffffff;
-  }
-  .out-background {
-    background-color: rgb(50, 197, 210);
-    border-color: rgb(50, 197, 210);
-    color: #ffffff;
-  }
-
-  .save-temp {
-    background-color: var(--mk-sys-color);
-    border-color: var(--mk-sys-color);
-    color: #ffffff;
-  }
-  .close-temp {
-    background-color: #ffffff;
-    border-color: #f5222d;
-    color: #f5222d;
-  }
-
-  .system-background {
-    background: var(--mk-sys-color);
-    border-color: var(--mk-sys-color);
-    color: #ffffff;
-  }
   .user {
     padding: 15px 30px 0px;
   }
@@ -145,10 +139,19 @@
   border: 1px solid #d8d8d8;
   border-radius: 4px;
   min-height: 66px;
+  overflow: hidden;
+
   .ant-btn {
     display: block;
     width: 100%;
     border: none;
+    color: rgba(0, 0, 0, 0.65);
+    border-radius: 0;
+  }
+  .ant-btn:not([disabled]):hover {
+    background-color: var(--mk-sys-color);
+    border-color: var(--mk-sys-color);
+    color: #ffffff;
   }
   .split {
     width: 100%;
diff --git a/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx b/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
index cbf864d..652b60d 100644
--- a/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/resetAttach/index.jsx
@@ -231,6 +231,7 @@
   }
 
   render() {
+    const { disabled } = this.props
     const { visible, upVisible, docVisible, files, list, documents, loading } = this.state
 
     return (
@@ -248,8 +249,8 @@
           destroyOnClose
         >
           {loading ? <Spin /> : null}
-          <Button type="link" className="attach-type-btn" disabled={loading} onClick={() => this.setState({upVisible: true})}>涓婁紶鏂版枃浠�</Button>
-          <Button type="link" className="attach-type-btn" disabled={loading} onClick={() => this.setState({docVisible: true, selectDocs: []})}>浠庝細璁$數瀛愭。妗堥�夋嫨</Button>
+          <Button type="link" className="attach-type-btn" disabled={loading || disabled} onClick={() => this.setState({upVisible: true})}>涓婁紶鏂版枃浠�</Button>
+          <Button type="link" className="attach-type-btn" disabled={loading || disabled} onClick={() => this.setState({docVisible: true, selectDocs: []})}>浠庝細璁$數瀛愭。妗堥�夋嫨</Button>
           <div className="attach-selected-list">
             {list.map(item => {
               return <div className="attach-item" key={item.id}>
@@ -259,7 +260,7 @@
                   <div>{item.data_name ? item.data_name + ' / ' : ''}{item.attachments_title}</div>
                 </div>
                 <div>
-                  <DeleteOutlined onClick={() => this.deleteFile(item.id)}/>
+                  {!disabled ? <DeleteOutlined onClick={() => this.deleteFile(item.id)}/> : null}
                 </div>
               </div>
             })}
diff --git a/src/tabviews/custom/components/module/voucher/resetRemark/index.jsx b/src/tabviews/custom/components/module/voucher/resetRemark/index.jsx
index a2a28b9..53af62e 100644
--- a/src/tabviews/custom/components/module/voucher/resetRemark/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/resetRemark/index.jsx
@@ -37,7 +37,7 @@
   }
 
   render() {
-    const { ID } = this.props
+    const { ID, disabled } = this.props
     const { visible, remark } = this.state
 
     return (
@@ -52,7 +52,7 @@
           onCancel={() => { this.setState({ visible: false })}}
           destroyOnClose
         >
-          <TextArea id={ID} defaultValue={remark} rows={6}/>
+          <TextArea id={ID} disabled={disabled} defaultValue={remark} rows={6}/>
         </Modal>
       </>
     )
diff --git a/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx b/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
index ba436ea..6edc5b7 100644
--- a/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
+++ b/src/tabviews/custom/components/module/voucher/voucherTable/index.jsx
@@ -712,7 +712,9 @@
       if (record.type === 'total') {
         children = <div className="content-wrap" style={{lineHeight: '60px'}}>鍚堣: {val}</div>
         colSpan = 2
-      } else {
+      } else if (record.$disabled) {
+        children = <div className="content-wrap">{val}</div>
+      } else  {
         extra = <PlusOutlined onClick={this.plusLine}/>
 
         if (editing) {
@@ -817,6 +819,17 @@
                   <span><InputNumber precision={4} className="inner-input" id={col.uuid + record.uuid + 'price'} defaultValue={record.net_unitprice || 0} onChange={(val) => this.onChange(val)} onPressEnter={this.pricePress} onBlur={this.priceBlur}/></span>
                 </span>
               </div>
+            } else if (record.$disabled) {
+              countNode = <div className="count-wrap">
+                <span style={{marginRight: '5px'}}>
+                  <span>鏁伴噺锛�</span>
+                  <span>{record.fcc_count || 0}</span>
+                </span>
+                <span>
+                  <span>鍗曚环锛�</span>
+                  <span>{record.net_unitprice || 0}</span>
+                </span>
+              </div>
             } else {
               countNode = <div className="count-wrap">
                 <span style={{marginRight: '5px'}} onClick={this.editCount}>
@@ -891,6 +904,21 @@
                   <span><InputNumber precision={2} className="inner-input" id={col.uuid + record.uuid + 'origin'} defaultValue={record.foreign_amount || 0} onChange={(val) => this.onChange(val)} onPressEnter={this.originPress} onBlur={this.originBlur}/></span>
                 </span>
               </div>
+            } else if (record.$disabled) {
+              currencyNode = <div className="count-wrap">
+                <span style={{marginRight: '5px'}}>
+                  <span>璐у竵锛�</span>
+                  <span>{record.exratename || ''}</span>
+                </span>
+                <span style={{marginRight: '5px'}}>
+                  <span>姹囩巼锛�</span>
+                  <span>{record.unitratio || 1}</span>
+                </span>
+                <span>
+                  <span>鍘熷竵锛�</span>
+                  <span>{record.foreign_amount || 0}</span>
+                </span>
+              </div>
             } else {
               currencyNode = <div className="count-wrap">
                 <span style={{marginRight: '5px'}} onClick={this.editCurrency}>
@@ -909,11 +937,19 @@
             }
           }
 
-          children = <div className="content-wrap" onClick={this.focus}>
-            {val}
-            {countNode}
-            {currencyNode}
-          </div>
+          if (record.$disabled) {
+            children = <div className="content-wrap">
+              {val}
+              {countNode}
+              {currencyNode}
+            </div>
+          } else {
+            children = <div className="content-wrap" onClick={this.focus}>
+              {val}
+              {countNode}
+              {currencyNode}
+            </div>
+          }
         }
       }
     } else if (col.field === 'debit') {
@@ -930,13 +966,23 @@
           }
           vals = (val * 100).toFixed(0).split('').reverse()
         }
-        children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
-          <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
-          <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
-        </div>
+        
+        if (record.$disabled) {
+          children = <div className={'money-uint' + (down ? ' down' : '')}>
+            <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
+            <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
+          </div>
+        } else {
+          children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
+            <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
+            <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
+          </div>
+        }
       }
     } else if (col.field === 'credit') {
-      extra = <CloseOutlined onClick={this.delVoucher}/>
+      if (record.type !== 'total' && !record.$disabled) {
+        extra = <CloseOutlined onClick={this.delVoucher}/>
+      }
 
       if (editing) {
         children = <InputNumber id={col.uuid + record.uuid} precision={2} defaultValue={record.credit} onChange={(val) => this.onChange(val)} onPressEnter={this.enterPress} onBlur={this.onBlur}/>
@@ -951,10 +997,18 @@
           }
           vals = (val * 100).toFixed(0).split('').reverse()
         }
-        children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
-        <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
-        <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
-      </div>
+
+        if (record.$disabled) {
+          children = <div className={'money-uint' + (down ? ' down' : '')}>
+            <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
+            <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
+          </div>
+        } else {
+          children = <div className={'money-uint' + (down ? ' down' : '')} onClick={this.focus}>
+            <span>{vals[10] || ''}</span> <span>{vals[9] || ''}</span> <span>{vals[8] || ''}</span> <span>{vals[7] || ''}</span> <span>{vals[6] || ''}</span> <span>{vals[5] || ''}</span>
+            <span>{vals[4] || ''}</span> <span>{vals[3] || ''}</span> <span>{vals[2] || ''}</span> <span>{vals[1] || ''}</span> <span className="last">{vals[0] || ''}</span>
+          </div>
+        }
       }
     }
 
@@ -966,17 +1020,17 @@
 
 class VoucherTable extends Component {
   static propTpyes = {
-    config: PropTypes.object,        // 鑿滃崟Id
-    data: PropTypes.any,             // 琛ㄦ牸鏁版嵁
-    loading: PropTypes.bool,         // 琛ㄦ牸鍔犺浇涓�
-    onChange: PropTypes.func,        // 琛ㄦ牸鍙樺姩
+    config: PropTypes.object,
+    data: PropTypes.any,
+    loading: PropTypes.bool,
+    onChange: PropTypes.func
   }
 
   state = {
     data: [],
     edData: [],
-    tableId: '',          // 琛ㄦ牸ID
-    columns: null,        // 鏄剧ず鍒�
+    tableId: '',
+    columns: null,
   }
 
   UNSAFE_componentWillMount () {
@@ -1105,9 +1159,11 @@
       return item
     })
 
+    let disabled = _data[0] && _data[0].$disabled ? true : false
+
     if (_data.length < 4) {
       for (let i = _data.length - 1; i < 4; i++) {
-        _data.push({uuid: Utils.getguid(), index: i + 1, subject_voucher_text: '', subject_code: '', subject_name: '', debit: '', credit: ''})
+        _data.push({uuid: Utils.getguid(), $disabled: disabled, index: i + 1, subject_voucher_text: '', subject_code: '', subject_name: '', debit: '', credit: ''})
       }
     }
     return _data
diff --git a/src/tabviews/custom/components/module/voucher/voucherTable/index.scss b/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
index 131b529..b25955b 100644
--- a/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
+++ b/src/tabviews/custom/components/module/voucher/voucherTable/index.scss
@@ -10,9 +10,8 @@
     position: absolute;
     bottom: 10px;
   }
-  >.ant-table-wrapper {
+  .ant-table-wrapper {
     position: relative;
-    z-index: 1;
   }
   .ant-table {
     color: inherit;
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 66f8c96..a468ec1 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -20,6 +20,51 @@
   '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
   '10:1': '10%', '3:4': '133.33%', '2:3': '150%', '9:16': '177.78%'
 }
+
+// 瀛楁閫忚
+const triggerLink = (e, item, record) => {
+  e.stopPropagation()
+
+  if (item.linkThdMenu) {
+    let __param = {
+      $BID: record.$$uuid
+    }
+
+    if (item.field) {
+      __param.$searchkey = item.field.toLowerCase()
+      __param.$searchval = record[item.field] || ''
+    }
+
+    Object.keys(record).forEach(key => {
+      if (/^\$/.test(key)) return
+      __param[key] = record[key]
+    })
+
+    let tabmenu = item.linkThdMenu
+
+    tabmenu.param = __param
+
+    MKEmitter.emit('modifyTabs', tabmenu, true)
+  } else if (item.linkurl) {
+    let src = item.linkurl
+
+    if (/@/.test(src)) {
+      src = src.replace(/@id@/ig, record.$$uuid)
+      src = src.replace(/@appkey@/ig, window.GLOB.appkey)
+      src = src.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+      src = src.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+      Object.keys(record).forEach(key => {
+        if (/^\$/.test(key)) return
+        let reg = new RegExp('@' + key + '@', 'ig')
+        src = src.replace(reg, record[key])
+      })
+    }
+
+    window.open(src)
+  }
+}
+
 class BodyRow extends React.Component {
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.props.data), fromJS(nextProps.data)) || this.props.className !== nextProps.className
@@ -107,7 +152,7 @@
   }
 
   render() {
-    let { col, config, record, className, style, triggerLink, ...resProps } = this.props
+    let { col, config, record, className, style, ...resProps } = this.props
 
     if (!col) return (<td {...resProps} className={className} style={style}/>)
 
@@ -169,10 +214,7 @@
       resProps.children = content
 
       if (!record.$disabled && (col.linkThdMenu || col.linkurl)) {
-        style = style || {}
-        style.cursor = 'pointer'
-
-        return (<td {...resProps} className={className} onDoubleClick={() => triggerLink(col, record)} style={style}/>)
+        return (<td {...resProps} className={className + ' clickable'} onClick={(e) => triggerLink(e, col, record)} style={style}/>)
       }
     } else if (col.type === 'number') {
       let content = ''
@@ -202,6 +244,7 @@
         }
   
         if (col.format === 'thdSeparator') {
+          content = content + ''
           content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
         }
   
@@ -243,10 +286,7 @@
       resProps.children = content
 
       if (!record.$disabled && (col.linkThdMenu || col.linkurl)) {
-        style = style || {}
-        style.cursor = 'pointer'
-
-        return (<td {...resProps} className={className} onDoubleClick={() => triggerLink(col, record)} style={style}/>)
+        return (<td {...resProps} className={className + ' clickable'} onClick={(e) => triggerLink(e, col, record)} style={style}/>)
       }
     } else if (col.type === 'picture') {
       let photos = ''
@@ -332,6 +372,17 @@
         } else {
           _href += '?' + _param
         }
+      } else if (/@/.test(_href)) {
+        _href = _href.replace(/@id@/ig, record.$$uuid || '')
+        _href = _href.replace(/@appkey@/ig, window.GLOB.appkey)
+        _href = _href.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        _href = _href.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        Object.keys(record).forEach(key => {
+          if (/^\$/.test(key)) return
+          let reg = new RegExp('@' + key + '@', 'ig')
+          _href = _href.replace(reg, record[key])
+        })
       }
 
       if (col.blur) {
@@ -455,7 +506,8 @@
     chgSelectData: PropTypes.func,   // 鏁版嵁鍒囨崲
     autoMatic: PropTypes.any,
     allSearch: PropTypes.any,
-    colsCtrls: PropTypes.any
+    colsCtrls: PropTypes.any,
+    parCtrl: PropTypes.any
   }
 
   state = {
@@ -504,10 +556,7 @@
             if (item.rowspan === 'true') {
               rowspans.push(item.field)
             }
-            if (item.type === 'index') {
-              item.field = '$Index'
-              item.type = 'text'
-            } else if (_format && !Math.floor(Math.random() * radio)) {
+            if (_format && !Math.floor(Math.random() * radio)) {
               item.blur = true
             }
   
@@ -528,7 +577,6 @@
                 record,
                 col: item,
                 config: item.type === 'custom' ? {setting, columns: fields} : null,
-                triggerLink: this.triggerLink
               })
             }
           }
@@ -604,7 +652,7 @@
   }
 
   UNSAFE_componentWillReceiveProps(nextProps) {
-    const { allSearch } = this.props
+    const { allSearch, parCtrl } = this.props
     const { allColumns } = this.state
 
     if (allSearch && !is(fromJS(allSearch), fromJS(nextProps.allSearch))) {
@@ -613,6 +661,36 @@
         columns: this.getCurColumns(allColumns, nextProps.allSearch)
       }, () => {
         this.setState({reseting: false})
+      })
+    } else if (parCtrl && !is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
+      let getColumns = (cols) => {
+        return cols.map(item => {
+          let cell = null
+    
+          if (item.type === 'colspan') {
+            cell = { title: item.label, align: item.Align }
+            cell.children = getColumns(item.subcols)
+          } else {
+            cell = {
+              align: item.Align,
+              dataIndex: item.uuid,
+              title: item.label,
+              sorter: (item.field || item.sortField) && item.IsSort === 'true',
+              width: item.Width || 120,
+              onCell: record => ({
+                record,
+                col: item,
+                config: item.type === 'custom' ? {setting: this.props.setting, columns: this.props.fields} : null,
+              })
+            }
+          }
+    
+          return cell
+        })
+      }
+
+      this.setState({
+        columns: getColumns(nextProps.columns)
       })
     }
   }
@@ -802,48 +880,6 @@
   
       MKEmitter.emit('resetSelectLine', MenuID, '', '')
       MKEmitter.emit('syncBalconyData', MenuID, [], false)
-    }
-  }
-
-  // 瀛楁閫忚
-  triggerLink = (item, record) => {
-    let __param = {
-      $searchkey: item.field,
-      $searchval: record[item.field] || '',
-      $BID: record.$$uuid
-    }
-
-    if (item.linkfields && item.linkfields.length > 0) {
-      item.linkfields.forEach(field => {
-        __param[field] = record[field] || ''
-      })
-    }
-
-    if (item.linkThdMenu) {
-      let tabmenu = item.linkThdMenu
-
-      tabmenu.param = __param
-
-      MKEmitter.emit('modifyTabs', tabmenu, true)
-    } else if (item.linkurl) {
-      let src = item.linkurl
-
-      let con = '?'
-
-      if (/\?/ig.test(src)) {
-        con = '&'
-      }
-
-      if (item.linkfields && item.linkfields.length > 0) {
-        item.linkfields.forEach(field => {
-          if (field.toLowerCase() === 'id') return
-          con += `${field}=${record[field] || ''}&`
-        })
-      }
-      
-      src = src + `${con}id=${record.$$uuid}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
-
-      window.open(src)
     }
   }
 
@@ -1076,7 +1112,7 @@
     if (!setting.doubleClick) return
     if (record.$disabled) return
 
-    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn')
+    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn', (record.$$uuid || '') + (record.$Index || ''))
   }
 
   render() {
@@ -1159,7 +1195,7 @@
     }
 
     return (
-      <div className={`normal-custom-table ${setting.tableHeader || ''} ${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-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
         }
diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss
index 6dbd534..a7688af 100644
--- a/src/tabviews/custom/components/share/normalTable/index.scss
+++ b/src/tabviews/custom/components/share/normalTable/index.scss
@@ -24,13 +24,20 @@
     position: absolute;
     bottom: 10px;
   }
-  >.ant-table-wrapper {
+  .ant-table-wrapper {
     position: relative;
-    z-index: 1;
   }
   .ant-table {
     color: inherit;
     font-size: inherit;
+  }
+
+  .clickable {
+    color: var(--mk-sys-color);
+    cursor: pointer;
+  }
+  .clickable:hover {
+    text-decoration: underline;
   }
 
   .mk-disabled {
@@ -201,6 +208,11 @@
     color: var(--mk-table-color);
   }
 }
+.normal-custom-table.mk-parity {
+  .ant-table-tbody tr:nth-child(even) {
+    background: #fafafa;
+  }
+}
 .normal-custom-table:not(.ghost) {
   .ant-table-small > .ant-table-content .ant-table-thead > tr > th {
     background-color: #fafafa!important;
diff --git a/src/tabviews/custom/components/share/normalheader/index.scss b/src/tabviews/custom/components/share/normalheader/index.scss
index 8de5a23..eb5e5b9 100644
--- a/src/tabviews/custom/components/share/normalheader/index.scss
+++ b/src/tabviews/custom/components/share/normalheader/index.scss
@@ -12,6 +12,7 @@
     text-decoration: inherit;
     font-weight: inherit;
     font-style: inherit;
+    font-family: inherit;
     float: left;
     line-height: inherit;
     margin-left: 10px;
@@ -38,6 +39,9 @@
         .ant-input-search-button {
           height: 28px;
         }
+        .ant-form-explain {
+          display: none;
+        }
       }
     }
   }
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index 2523935..34289a8 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -294,9 +294,7 @@
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item}/>
-          </Col>
+          <NormalGroup config={item} style={style} key={item.uuid}/>
         )
       } else if (item.type === 'form' && item.subtype === 'simpleform') {
         return (
diff --git a/src/tabviews/custom/components/table/base-table/index.jsx b/src/tabviews/custom/components/table/base-table/index.jsx
index ec29c8f..bc2b635 100644
--- a/src/tabviews/custom/components/table/base-table/index.jsx
+++ b/src/tabviews/custom/components/table/base-table/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { notification, Modal } from 'antd'
+import { notification } from 'antd'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -143,6 +143,7 @@
     this.requestId = config.uuid + new Date().getTime()
 
     let result = await Api.genericInterface(param, setting.js_script, '', this.requestId)
+
     if (result.status) {
       if (result.$requestId && this.requestId !== result.$requestId) return
 
@@ -228,19 +229,7 @@
         }
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
@@ -250,18 +239,7 @@
         MKEmitter.emit('autoMaticError', config.MenuID)
       }
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -383,11 +361,8 @@
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -598,8 +573,8 @@
       } else {
         this.reloadtable(btn, id)
       }
-    } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.reloadtable(btn, id)
     }
diff --git a/src/tabviews/custom/components/table/edit-table/index.jsx b/src/tabviews/custom/components/table/edit-table/index.jsx
index 14776ec..ffd5efc 100644
--- a/src/tabviews/custom/components/table/edit-table/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { notification, Modal } from 'antd'
+import moment from 'moment'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -75,7 +75,6 @@
       }
     })
 
-    let _columns = []
     let initId = ''
 
     setting.hasSubmit = false
@@ -83,6 +82,7 @@
       setting.commit = 'change'
     }
 
+    let index = 0
     let getColumns = (cols) => {
       return cols.filter(item => {
         if (item.Hide === 'true') return false
@@ -96,6 +96,8 @@
             return false
           }
         } else if (item.type === 'custom') {
+          item.config = {setting: _config.setting, columns: _config.columns}
+
           item.elements.forEach(btn => {
             if (btn.eleType !== 'button') return
             if (btn.funcType === 'addline') {
@@ -108,15 +110,16 @@
             }
           })
         } else {
-          if (item.type === 'index') {
-            item.field = '$Index'
-            item.type = 'text'
-          }
-
           if (item.editable === 'true') {
+            item.$sort = index
+            index++
+
             setting.hasSubmit = setting.commit !== 'change'
             item.$ctrl = setting.commit === 'change'
             
+            if (item.ctrlField) {
+              item.ctrlValue = item.ctrlValue.split(',')
+            }
             if (!initId) {
               initId = item.uuid
             }
@@ -131,8 +134,26 @@
             }
 
             if (item.type === 'number') {
-
+              if (item.clearField) {
+                _config.columns.forEach(cell => {
+                  if (cell.field === item.clearField) {
+                    item.clearName = cell.label
+                  }
+                })
+              }
+            } else if (item.editType === 'date') {
+              item.format = 'YYYY-MM-DD'
+  
+              if (item.precision === 'hour') {
+                item.format = 'YYYY-MM-DD HH'
+              } else if (item.precision === 'minute') {
+                item.format = 'YYYY-MM-DD HH:mm'
+              } else if (item.precision === 'second') {
+                item.format = 'YYYY-MM-DD HH:mm:ss'
+              }
             } else if (item.editType === 'select') {
+              item.map = new Map()
+
               item.options = item.options || []
               item.options = item.options.filter(cell => {
                 cell.value = cell.Value
@@ -140,6 +161,12 @@
         
                 return !cell.Hide
               })
+
+              if (item.resourceType !== '1') {
+                item.options.forEach(cell => {
+                  item.map.set(cell.value, cell.label)
+                })
+              }
             } else if (item.editType === 'popSelect') {
               if (item.pops) {
                 item.pops.forEach(cell => {
@@ -158,7 +185,12 @@
       })
     }
 
-    _columns = getColumns(_config.cols)
+    _config.cols = getColumns(_config.cols)
+
+    let _columns = _config.cols
+    if (_config.hasExtend) {
+      _columns = this.getCols(_config.cols, BData, _config.setting.extendTime)
+    }
 
     setting.initId = initId
 
@@ -259,6 +291,132 @@
     config.arr_field = arrfield.join(',')
   }
 
+  getCols = (cols, BData, time) => {
+    let _cols = []
+    let weeks = ['鏄熸湡鏃�', '鏄熸湡涓�', '鏄熸湡浜�', '鏄熸湡涓�', '鏄熸湡鍥�', '鏄熸湡浜�', '鏄熸湡鍏�']
+
+    let excols = (col) => {
+      let _s = []
+      let _marks = col.marks || []
+      let names = []
+      let fields = []
+
+      for (let i = 0; i < col.quota; i++) {
+        fields.push(col.field + (i === 0 ? '' : i))
+
+        if (col.colUnit === 'day') {
+          let hasweek = col.dayFormat.indexOf('week') > -1
+          let format = col.dayFormat.replace(/\sweek/, '')
+          let day = moment().add(col.shift + i, 'days').format(format)
+
+          if (hasweek) {
+            let _w = moment().add(col.shift + i, 'days').weekday()
+            day = day + ' ' + weeks[_w]
+          }
+
+          names.push(day)
+        } else {
+          let format = col.hourFormat
+          if (format === 'H point') {
+            format = 'H鐐�'
+          }
+
+          let hour = moment(time).add(col.shift + i, 'hours').format(format)
+
+          if (format === 'h:00') {
+            if (hour === '12:00') {
+              hour = hour + ' pm'
+            } else if (hour === moment(time).add(col.shift + i, 'hours').format('H:00')) {
+              hour = hour + ' am'
+            } else {
+              hour = hour + ' pm'
+            }
+          }
+          names.push(hour)
+        }
+      }
+
+      if (col.supField) {
+        names = []
+        let val = ''
+        if (BData) {
+          let field = col.supField.toLowerCase()
+          Object.keys(BData).forEach(key => {
+            if (key.toLowerCase() === field) {
+              val = BData[key] + ''
+            }
+          })
+        }
+
+        if (val) {
+          names = val.split(',')
+
+          if (names.length > fields.length) {
+            names.length = fields.length
+          } else if (fields.length > names.length) {
+            fields.length = names.length
+          }
+        }
+      }
+
+      if (names.length === 0) return _s
+
+      _s = fields.map((f, i) => {
+        return {
+          type: 'text',
+          Align: col.Align,
+          Width: col.Width,
+          field: f,
+          label: names[i],
+          uuid: col.uuid + i,
+          marks: _marks.filter(mark => mark.field[0] === f || !fields.includes(mark.field[0]))
+        }
+      })
+
+      return _s
+    }
+
+    cols.forEach(col => {
+      if (col.type === 'extend') {
+        let exs = excols(col)
+        _cols.push(...exs)
+      } else if (col.type === 'colspan') {
+        let subs = []
+        col.subcols.forEach(subcol => {
+          if (subcol.type === 'extend') {
+            let exs = excols(subcol)
+            subs.push(...exs)
+          } else {
+            subs.push(col)
+          }
+        })
+
+        if (subs.length) {
+          _cols.push({...col, subcols: subs})
+        }
+      } else {
+        _cols.push(col)
+      }
+    })
+
+    return _cols
+  }
+
+  resetCols = (BData) => {
+    const { config, setting } = this.state
+
+    MKEmitter.emit('transferData' + setting.tableId, [], 'clear')
+
+    let columns = this.getCols(config.cols, BData, config.setting.extendTime)
+
+    this.setState({
+      columns: columns,
+      data: [],
+      selectedData: [],
+      total: 0
+    })
+  }
+
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    * @param { Boolean } reset  琛ㄦ牸鏄惁閲嶇疆
@@ -355,36 +513,13 @@
 
       MKEmitter.emit('transferData' + setting.tableId, data)
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -487,11 +622,8 @@
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -582,10 +714,14 @@
   }
 
   resetParentParam = (MenuID, id, data) => {
-    const { setting } = this.state
+    const { setting, config } = this.state
 
     if (!setting.supModule || setting.supModule !== MenuID) return
     if (id !== this.state.BID || id !== '') {
+      if (config.parCtrl) {
+        this.resetCols(data)
+      }
+
       this.setState({
         pageIndex: 1,
         BID: id,
@@ -617,8 +753,8 @@
       } else {
         this.reloadtable(btn)
       }
-    } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.reloadtable(btn)
     }
@@ -722,6 +858,7 @@
           submit={config.submit}
           fields={config.columns}
           total={this.state.total}
+          parCtrl={config.parCtrl}
           colsCtrls={config.colsCtrls}
           lineMarks={config.lineMarks}
           loading={this.state.loading}
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 4bcdb13..762b303 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -562,6 +562,10 @@
 
       if (config.noValue === 'hide' && !value) {
         value = 0
+      }
+
+      if (config.required === 'true' && !value) {
+        err = `${config.label}涓嶅彲涓�${config.noValue === 'hide' ? '绌�' : '0'}`
       } else {
         if (typeof(config.max) === 'number' && value > config.max) {
           err = config.label + '鏈�澶т负' + config.max
@@ -727,7 +731,7 @@
   }
 
   render() {
-    let { col, config, record, style, className, ...resProps } = this.props
+    let { col, record, style, className, ...resProps } = this.props
     const { editing } = this.state
 
     if (!col) return (<td {...resProps} className={className} style={style}/>)
@@ -747,10 +751,10 @@
       if (col.editType === 'select' && col.options.length > 0) {
         content = col.map.get(content) || content
       } else if (col.editType === 'switch') {
-        if (content === config.openVal) {
-          content = config.openText
-        } else if (content === config.closeVal) {
-          content = config.closeText
+        if (content === col.openVal) {
+          content = col.openText
+        } else if (content === col.closeVal) {
+          content = col.closeText
         }
       } else if (col.editType === 'popSelect') {
         if (col.showField) {
@@ -866,6 +870,7 @@
         }
   
         if (col.format === 'thdSeparator') {
+          content = content + ''
           content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
         }
   
@@ -1009,7 +1014,7 @@
       }
 
       children = (
-        <CardCellComponent data={record} cards={config} elements={col.elements}/>
+        <CardCellComponent data={record} cards={col.config} elements={col.elements}/>
       )
     }
 
@@ -1040,7 +1045,7 @@
   }
 
   render() {
-    let { col, config, record, style, className, ...resProps } = this.props
+    let { col, record, style, className, ...resProps } = this.props
 
     if (!col) return (<td {...resProps} className={className} style={style}/>)
 
@@ -1091,10 +1096,10 @@
         if (col.editType === 'select' && col.options.length > 0) {
           content = col.map.get(content) || content
         } else if (col.editType === 'switch') {
-          if (content === config.openVal) {
-            content = config.openText
-          } else if (content === config.closeVal) {
-            content = config.closeText
+          if (content === col.openVal) {
+            content = col.openText
+          } else if (content === col.closeVal) {
+            content = col.closeText
           }
         } else if (col.editType === 'popSelect') {
           if (col.showField) {
@@ -1190,6 +1195,7 @@
           }
     
           if (col.format === 'thdSeparator') {
+            content = content + ''
             content = content.replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,')
           }
     
@@ -1322,7 +1328,7 @@
       }
 
       children = (
-        <CardCellComponent data={record} cards={config} elements={col.elements}/>
+        <CardCellComponent data={record} cards={col.config} elements={col.elements}/>
       )
     }
 
@@ -1383,7 +1389,6 @@
     let deForms = []
     let _forms = {}
     let hasBid = false
-    let index = 0
     let checkForms = []
     let allForms = []
 
@@ -1396,25 +1401,12 @@
           cell.children = getColumns(item.subcols, sk || item.uuid)
         } else {
           if (item.editable === 'true') {
-            item.$sort = index
-            index++
             _forms[item.field] = item
 
             allForms.push({uuid: sk || item.uuid, field: item.field})
             checkForms.push(item.field)
 
-            if (item.ctrlField) {
-              item.ctrlValue = item.ctrlValue.split(',')
-            }
-            
-            if (item.type === 'number' && item.clearField) {
-              fields.forEach(cell => {
-                if (cell.field === item.clearField) {
-                  item.clearName = cell.label
-                }
-              })
-            } else if (item.type === 'text' && item.editType === 'select') {
-              item.map = new Map()
+            if (item.type === 'text' && item.editType === 'select') {
               if (item.resourceType === '1') {
                 let _option = Utils.getSelectQueryOptions(item)
   
@@ -1426,20 +1418,6 @@
                 item.arr_field = _option.field
         
                 deForms.push(item)
-              } else {
-                item.options.forEach(cell => {
-                  item.map.set(cell.value, cell.label)
-                })
-              }
-            } else if (item.type === 'text' && item.editType === 'date') {
-              item.format = 'YYYY-MM-DD'
-  
-              if (item.precision === 'hour') {
-                item.format = 'YYYY-MM-DD HH'
-              } else if (item.precision === 'minute') {
-                item.format = 'YYYY-MM-DD HH:mm'
-              } else if (item.precision === 'second') {
-                item.format = 'YYYY-MM-DD HH:mm:ss'
               }
             }
           }
@@ -1459,8 +1437,7 @@
             $key: item.uuid,
             onCell: record => ({
               record,
-              col: item,
-              config: item.type === 'custom' ? {setting, columns: fields} : null,
+              col: item
             })
           }
         }
@@ -1537,11 +1514,44 @@
   }
 
   UNSAFE_componentWillReceiveProps(nextProps) {
-    const { BID } = this.props
+    const { BID, parCtrl } = this.props
     const { deForms } = this.state
 
     if (deForms && nextProps.BID !== BID) {
       this.improveActionForm(deForms, nextProps.BID)
+    }
+    if (parCtrl && !is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
+      let getColumns = (cols, sk) => {
+        return cols.map(item => {
+          let cell = null
+    
+          if (item.type === 'colspan') {
+            cell = { title: item.label, align: item.Align, $key: item.uuid }
+            cell.children = getColumns(item.subcols, sk || item.uuid)
+          } else {
+            cell = {
+              align: item.Align,
+              dataIndex: item.uuid,
+              title: item.editable === 'true' ? <span>{item.label}<EditOutlined className="system-color mk-edit-sign"/></span> : item.label,
+              sorter: (item.field || item.sortField) && item.IsSort === 'true',
+              width: item.Width || 120,
+              $key: item.uuid,
+              onCell: record => ({
+                record,
+                col: item
+              })
+            }
+          }
+    
+          return cell
+        })
+      }
+  
+      let _columns = getColumns(nextProps.columns)
+
+      this.setState({
+        columns: _columns
+      })
     }
   }
 
@@ -1656,7 +1666,9 @@
       } else if (col.type === 'number') {
         let val = record[col.field]
 
-        if (col.noValue === 'hide' && !val) {
+        if (col.required === 'true' && !val) {
+          err = `${col.label}涓嶅彲涓�${col.noValue === 'hide' ? '绌�' : '0'}`
+        } else if (col.noValue === 'hide' && !val) {
           if (col.clearField && checkForms.includes(col.clearField) && !record[col.clearField]) {
             err = `璇峰~鍐� ${col.label} 鎴� ${col.clearName}`
           }
@@ -1748,7 +1760,10 @@
   transferData = (data, type) => {
     const { edData, tableId } = this.state
 
-    if (type === 'delete') {
+    if (type === 'clear') {
+      this.setState({edData: [], midData: []})
+      return
+    } else if (type === 'delete') {
 
     } else if (type === 'line') {
       let value = ''
@@ -2270,7 +2285,9 @@
           item[col.field] = val
         } else if (col.type === 'number') {
           let val = item[col.field]
-          if (col.noValue === 'hide' && !val) {
+          if (col.required === 'true' && !val) {
+            err = `${col.label}涓嶅彲涓�${col.noValue === 'hide' ? '绌�' : '0'}`
+          } else if (col.noValue === 'hide' && !val) {
             if (col.clearField && checkForms.includes(col.clearField) && !item[col.clearField]) {
               let msg = `璇峰~鍐� ${col.label} 鎴� ${col.clearName}`
               if (!line.includes(msg)) {
@@ -2652,7 +2669,7 @@
         {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>
         </div> : null}
-        <div className={`edit-custom-table ${setting.tableHeader || ''} ${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-height' : ''} ${setting.mode || ''} table-vertical-${setting.vertical || ''} mk-edit-${setting.editType || 'simple'}`} style={style}>
           <Table
             rowKey="$$uuid"
             components={components}
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 a3362b3..52f01f0 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -7,9 +7,8 @@
   --mk-table-font-size: 14px;
   --mk-table-font-weight: normal;
 
-  >.ant-table-wrapper {
+  .ant-table-wrapper {
     position: relative;
-    // z-index: 1;
   }
   .ant-table-placeholder {
     border-top-color: var(--mk-table-border-color);
@@ -269,6 +268,11 @@
   //   }
   // }
 }
+.edit-custom-table.mk-parity {
+  .ant-table-tbody tr:nth-child(even) {
+    background: #fafafa;
+  }
+}
 .edit-custom-table.mk-edit-simple {
   table tbody tr td {
     min-height: 32px;
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index 92c7018..fd31261 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -1,7 +1,8 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { notification, Collapse, Modal } from 'antd'
+import { Collapse } from 'antd'
+import moment from 'moment'
 
 import Api from '@/api'
 import UtilsDM from '@/utils/utils-datamanage.js'
@@ -43,6 +44,7 @@
   }
 
   loaded = false
+  supModules = []
 
   /**
    * @description 鍒濆鍖栧鐞�
@@ -151,6 +153,11 @@
       _config.colsCtrls = null
     }
 
+    let columns = _config.cols
+    if (_config.hasExtend) {
+      columns = this.getCols(_config.cols, BData, _config.setting.extendTime)
+    }
+
     this.setState({
       pageSize: setting.pageSize || 10,
       BID: BID || '',
@@ -160,7 +167,7 @@
       config: _config,
       setting: setting,
       actions: _config.action,
-      columns: _config.cols,
+      columns: columns,
       search: _config.$searches,
       allSearch
     })
@@ -378,6 +385,130 @@
     MKEmitter.removeListener('transferSyncData', this.transferSyncData)
   }
 
+  getCols = (cols, BData, time) => {
+    let _cols = []
+    let weeks = ['鏄熸湡鏃�', '鏄熸湡涓�', '鏄熸湡浜�', '鏄熸湡涓�', '鏄熸湡鍥�', '鏄熸湡浜�', '鏄熸湡鍏�']
+
+    let excols = (col) => {
+      let _s = []
+      let _marks = col.marks || []
+      let names = []
+      let fields = []
+
+      for (let i = 0; i < col.quota; i++) {
+        fields.push(col.field + (i === 0 ? '' : i))
+
+        if (col.colUnit === 'day') {
+          let hasweek = col.dayFormat.indexOf('week') > -1
+          let format = col.dayFormat.replace(/\sweek/, '')
+          let day = moment().add(col.shift + i, 'days').format(format)
+
+          if (hasweek) {
+            let _w = moment().add(col.shift + i, 'days').weekday()
+            day = day + ' ' + weeks[_w]
+          }
+
+          names.push(day)
+        } else {
+          let format = col.hourFormat
+          if (format === 'H point') {
+            format = 'H鐐�'
+          }
+
+          let hour = moment(time).add(col.shift + i, 'hours').format(format)
+
+          if (format === 'h:00') {
+            if (hour === '12:00') {
+              hour = hour + ' pm'
+            } else if (hour === moment(time).add(col.shift + i, 'hours').format('H:00')) {
+              hour = hour + ' am'
+            } else {
+              hour = hour + ' pm'
+            }
+          }
+          names.push(hour)
+        }
+      }
+
+      if (col.supField) {
+        names = []
+        let val = ''
+        if (BData) {
+          let field = col.supField.toLowerCase()
+          Object.keys(BData).forEach(key => {
+            if (key.toLowerCase() === field) {
+              val = BData[key] + ''
+            }
+          })
+        }
+
+        if (val) {
+          names = val.split(',')
+
+          if (names.length > fields.length) {
+            names.length = fields.length
+          } else if (fields.length > names.length) {
+            fields.length = names.length
+          }
+        }
+      }
+
+      if (names.length === 0) return _s
+
+      _s = fields.map((f, i) => {
+        return {
+          type: 'text',
+          Align: col.Align,
+          Width: col.Width,
+          field: f,
+          label: names[i],
+          uuid: col.uuid + i,
+          marks: _marks.filter(mark => mark.field[0] === f || !fields.includes(mark.field[0]))
+        }
+      })
+
+      return _s
+    }
+
+    cols.forEach(col => {
+      if (col.type === 'extend') {
+        let exs = excols(col)
+        _cols.push(...exs)
+      } else if (col.type === 'colspan') {
+        let subs = []
+        col.subcols.forEach(subcol => {
+          if (subcol.type === 'extend') {
+            let exs = excols(subcol)
+            subs.push(...exs)
+          } else {
+            subs.push(col)
+          }
+        })
+
+        if (subs.length) {
+          _cols.push({...col, subcols: subs})
+        }
+      } else {
+        _cols.push(col)
+      }
+    })
+
+    return _cols
+  }
+
+  resetCols = (BData) => {
+    const { config } = this.state
+
+    let columns = this.getCols(config.cols, BData, config.setting.extendTime)
+
+    this.setState({
+      columns: columns,
+      data: [],
+      selectedData: [],
+      total: 0
+    })
+  }
+
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    * @param { Boolean } reset  琛ㄦ牸鏄惁閲嶇疆
@@ -529,37 +660,14 @@
         }
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -685,11 +793,8 @@
       this.setState({
         loading: false
       })
-      notification.error({
-        top: 92,
-        message: result.message,
-        duration: 10
-      })
+      
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -780,20 +885,44 @@
   }
 
   resetParentParam = (MenuID, id, data) => {
-    const { setting } = this.state
+    const { config, setting } = this.state
 
-    if (!setting.supModule || setting.supModule !== MenuID) return
+    if (config.supNodes) {
+      if (!config.supNodes.includes(MenuID)) return
+      this.supModules = this.supModules.filter(item => item.key !== MenuID)
+      let bid = ''
+      let _data = null
 
-    if (id !== this.state.BID || id !== '') {
-      this.setState({
-        pageIndex: 1,
-        BID: id,
-        BData: data
-      }, () => {
-        if (!setting.checkBid) {
+      if (id) {
+        this.supModules.push({key: MenuID, value: id, data})
+      }
+      if (this.supModules.length > 0) {
+        bid = this.supModules[this.supModules.length - 1].value
+        _data = this.supModules[this.supModules.length - 1].data
+      }
+
+      if (bid !== this.state.BID || bid !== '') {
+        this.setState({ BID: bid, BData: _data, pageIndex: 1 }, () => {
           this.loadmaindata(true, 'true')
+        })
+      }
+    } else {
+      if (!setting.supModule || setting.supModule !== MenuID) return
+  
+      if (id !== this.state.BID || id !== '') {
+        if (config.parCtrl) {
+          this.resetCols(data)
         }
-      })
+        this.setState({
+          pageIndex: 1,
+          BID: id,
+          BData: data
+        }, () => {
+          if (!setting.checkBid) {
+            this.loadmaindata(true, 'true')
+          }
+        })
+      }
     }
   }
 
@@ -808,16 +937,41 @@
 
     if (config.uuid !== menuId) return
 
-    if (position === 'line' || position === 'line_grid') {
-      if (lines && lines.length === 1) {
-        this.loadLinedata(lines[0].$$uuid, position)
+    if (config.supNodes) {
+      if (['mainline', 'maingrid', 'popclose'].includes(position)) {
+        let supNode = this.supModules[this.supModules.length - 1]
+        config.supNodes.forEach((item, i) => {
+          setTimeout(() => {
+            if (supNode && supNode.key === item) {
+              MKEmitter.emit('reloadData', item, supNode.value)
+            } else {
+              MKEmitter.emit('reloadData', item)
+            }
+          }, i * 10)
+        })
+      } else {
+        if (position === 'line' || position === 'line_grid') {
+          if (lines && lines.length === 1) {
+            this.loadLinedata(lines[0].$$uuid, position)
+          } else {
+            this.reloadtable(btn, id)
+          }
+        } else {
+          this.reloadtable(btn, id)
+        }
+      }
+    } else {
+      if (position === 'line' || position === 'line_grid') {
+        if (lines && lines.length === 1) {
+          this.loadLinedata(lines[0].$$uuid, position)
+        } else {
+          this.reloadtable(btn, id)
+        }
+      } else if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+        MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
       } else {
         this.reloadtable(btn, id)
       }
-    } else if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
-    } else {
-      this.reloadtable(btn, id)
     }
   }
 
@@ -883,6 +1037,7 @@
         data={this.state.data}
         fields={config.columns}
         total={this.state.total}
+        parCtrl={config.parCtrl}
         colsCtrls={config.colsCtrls}
         lineMarks={config.lineMarks}
         loading={this.state.loading}
diff --git a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
index 698328e..29e50f7 100644
--- a/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
+++ b/src/tabviews/custom/components/timeline/normal-timeline/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, notification, Timeline, Empty, Modal } from 'antd'
+import { Spin, notification, Timeline, Empty } from 'antd'
 
 import Api from '@/api'
 import MkIcon from '@/components/mk-icon'
@@ -252,8 +252,8 @@
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -377,37 +377,14 @@
         }
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
diff --git a/src/tabviews/custom/components/tree/antd-tree/index.jsx b/src/tabviews/custom/components/tree/antd-tree/index.jsx
index 721d876..35b14ec 100644
--- a/src/tabviews/custom/components/tree/antd-tree/index.jsx
+++ b/src/tabviews/custom/components/tree/antd-tree/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Spin, Empty, notification, Input, Tree, Modal, Dropdown } from 'antd'
+import { Spin, Empty, Input, Tree, Dropdown } from 'antd'
 import { FolderOpenOutlined, FolderOutlined, FileOutlined, MoreOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -31,6 +31,7 @@
     treeNodes: null,           // 鍒楄〃鏁版嵁闆�
     expandedKeys: [],          // 灞曞紑鐨勬爲鑺傜偣
     selectedKeys: [],          // 閫変腑鐨勬爲鑺傜偣
+    lineActions: [],
     selected: false            // 閫変腑棣栬
   }
 
@@ -71,13 +72,28 @@
       }
     }
 
+    let lineActions = []
+    _config.action = _config.action || []
+    _config.action = _config.action.filter(item => {
+      if (item.Ot === 'requiredSgl') {
+        lineActions.push(item)
+        return false
+      }
+      return true
+    })
+
     _config.wrap.contentHeight = config.wrap.title || config.wrap.searchable === 'true' ? 'calc(100% - 45px)' : '100%'
+
+    if (_config.wrap.lineHeight) {
+      _config.style['--mk-tree-line-height'] = _config.wrap.lineHeight + 'px'
+    }
 
     this.setState({
       selected: _config.wrap.selected === 'true',
       config: _config,
       data: _data,
-      BID: BID || ''
+      BID: BID || '',
+      lineActions
     })
   }
 
@@ -254,13 +270,13 @@
    * @param {*} position   // 鍒锋柊浣嶇疆
    * @param {*} btn        // 鎵ц鐨勬寜閽�
    */
-  refreshByButtonResult = (menuId, position, btn) => {
+  refreshByButtonResult = (menuId, position) => {
     const { config, BID } = this.state
 
     if (config.uuid !== menuId) return
 
-    if ((position === 'mainline' || position === 'popclose') && config.setting.supModule && BID) { // 鍒锋柊婧愮粍浠舵椂锛岄檮甯﹀埛鏂颁笂绾ц涓庡綋鍓嶇粍浠�
-      MKEmitter.emit('reloadData', config.setting.supModule, BID)
+    if (['mainline', 'maingrid', 'popclose'].includes(position) && config.setting.supModule) {
+      MKEmitter.emit('reloadData', config.setting.supModule, position === 'maingrid' ? '' : BID)
     } else {
       this.loadData()
     }
@@ -321,37 +337,14 @@
         }
       }
 
-      if (result.message) {
-        if (result.ErrCode === 'Y') {
-          Modal.success({
-            title: result.message
-          })
-        } else if (result.ErrCode === 'S') {
-          notification.success({
-            top: 92,
-            message: result.message,
-            duration: 2
-          })
-        }
-      }
+      UtilsDM.querySuccess(result)
     } else {
       this.setState({
         loading: false
       })
       this.timer && this.timer.stop()
       
-      if (!result.message) return
-      if (result.ErrCode === 'N') {
-        Modal.error({
-          title: result.message,
-        })
-      } else if (result.ErrCode !== '-2') {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
-      }
+      UtilsDM.queryFail(result)
     }
   }
 
@@ -376,9 +369,9 @@
     let hasSelectKey = false
 
     data.forEach(item => {
-      let pval = item[config.wrap.parentField]
-      let val = item[config.wrap.valueField]
-      let uuid = item[config.setting.primaryKey] || ''
+      let pval = item[config.wrap.parentField] + ''
+      let val = item[config.wrap.valueField] + ''
+      let uuid = item[config.setting.primaryKey] + ''
 
       if (!val || logMap.has(val)) return
 
@@ -528,30 +521,45 @@
     })
   }
 
-  renderActionTreeNodes = (nodes) => {
+  renderActionTreeNodes = (nodes, actShow) => {
     return nodes.map(item => {
-      let title = <>
-        {item.$title}
-        <Dropdown overlay={
-          <div className="mk-tree-dropdown-wrap" onClick={(e) => e.stopPropagation()}>
-            <MainAction
-              BID={this.state.BID}
-              BData={this.state.BData}
-              setting={this.state.config.setting}
-              actions={this.state.config.action}
-              columns={this.state.config.columns}
-              selectedData={[{...item, children: ''}]}
-            />
-          </div>
-        } placement="bottomCenter" trigger={['hover']}>
-          <MoreOutlined onClick={(e) => e.stopPropagation()}/>
-        </Dropdown>
-      </>
+      let title = null
+      if (actShow === 'line') {
+        title = <>
+          {item.$title}
+          <MainAction
+            BID={this.state.BID}
+            BData={this.state.BData}
+            setting={this.state.config.setting}
+            actions={this.state.lineActions}
+            columns={this.state.config.columns}
+            selectedData={[{...item, children: ''}]}
+          />
+        </>
+      } else {
+        title = <>
+          {item.$title}
+          <Dropdown overlay={
+            <div className="mk-tree-dropdown-wrap" onClick={(e) => e.stopPropagation()}>
+              <MainAction
+                BID={this.state.BID}
+                BData={this.state.BData}
+                setting={this.state.config.setting}
+                actions={this.state.lineActions}
+                columns={this.state.config.columns}
+                selectedData={[{...item, children: ''}]}
+              />
+            </div>
+          } placement="bottomCenter" trigger={['hover']}>
+            <MoreOutlined onClick={(e) => e.stopPropagation()}/>
+          </Dropdown>
+        </>
+      }
 
       if (item.children) {
         return (
           <TreeNode icon={<span><FolderOpenOutlined /><FolderOutlined /></span>} title={title} key={item.$key} dataRef={item}>
-            {this.renderActionTreeNodes(item.children)}
+            {this.renderActionTreeNodes(item.children, actShow)}
           </TreeNode>
         )
       }
@@ -614,9 +622,7 @@
   }
 
   render() {
-    const { config, loading, treeNodes, expandedKeys, selectedKeys } = this.state
-
-    let extra = config.action && config.action.length > 0
+    const { BID, BData, config, loading, treeNodes, expandedKeys, selectedKeys, lineActions } = this.state
 
     return (
       <div className="custom-tree-box" id={'anchor' + config.uuid} style={config.style}>
@@ -630,18 +636,26 @@
           <span className={'title ' + (config.wrap.searchable !== 'true' ? 'search-unable' : '')}>{config.wrap.title}</span>
           {config.wrap.searchable === 'true' ? <Search allowClear onSearch={this.treeFilter} /> : null}
         </div> : null}
+        {config.action.length ? <MainAction
+          BID={BID}
+          setting={config.setting}
+          actions={config.action}
+          BData={BData}
+          columns={config.columns}
+          selectedData={[]}
+        /> : null}
         {treeNodes && treeNodes.length > 0 ? <div className="tree-box" style={{height: config.wrap.contentHeight}}>
           <Tree
             blockNode
             onSelect={this.selectTreeNode}
             expandedKeys={expandedKeys}
             selectedKeys={selectedKeys}
-            onRightClick={!extra ? this.changeExpandedAllKeys : null}
+            onRightClick={!lineActions.length ? this.changeExpandedAllKeys : null}
             onExpand={this.changeExpandedKeys}
             showIcon={config.wrap.showIcon === 'true'}
             showLine={config.wrap.showLine === 'true'}
           >
-            {!extra ? this.renderTreeNodes(treeNodes) : this.renderActionTreeNodes(treeNodes)}
+            {!lineActions.length ? this.renderTreeNodes(treeNodes) : this.renderActionTreeNodes(treeNodes, config.wrap.actShow)}
           </Tree>
         </div> : null}
         {treeNodes && treeNodes.length === 0 ? <Empty description={false}/> : null}
diff --git a/src/tabviews/custom/components/tree/antd-tree/index.scss b/src/tabviews/custom/components/tree/antd-tree/index.scss
index eb5df34..84d2037 100644
--- a/src/tabviews/custom/components/tree/antd-tree/index.scss
+++ b/src/tabviews/custom/components/tree/antd-tree/index.scss
@@ -5,6 +5,7 @@
   background-repeat: no-repeat;
   background-size: cover;
   min-height: 50px;
+  --mk-tree-line-height: 24px;
 
   .tree-header {
     position: relative;
@@ -18,6 +19,7 @@
       text-decoration: inherit;
       font-weight: inherit;
       font-style: inherit;
+      font-family: inherit;
       float: left;
       line-height: 45px;
       margin-left: 10px;
@@ -44,6 +46,39 @@
       }
     }
   }
+  .ant-tree-title {
+    .button-list.toolbar-button {
+      position: absolute;
+      right: 0px;
+      top: 0px;
+      padding: 0px;
+      min-height: 24px;
+      height: var(--mk-tree-line-height);
+
+      button {
+        min-width: 20px;
+        margin-bottom: 0px !important;
+        min-height: 24px;
+        border-width: 0px;
+        vertical-align: middle;
+      }
+    }
+  }
+  .ant-tree-node-content-wrapper {
+    .button-list.toolbar-button {
+      opacity: 0;
+      transition: all 0.3s;
+    }
+  }
+  .ant-tree-node-content-wrapper:hover {
+    .button-list.toolbar-button {
+      opacity: 1;
+    }
+  }
+  .ant-tree li .ant-tree-node-content-wrapper, .ant-tree li span.ant-tree-switcher, .ant-tree li span.ant-tree-iconEle {
+    height: var(--mk-tree-line-height);
+    line-height: var(--mk-tree-line-height);
+  }
   .tree-box {
     overflow: auto;
     padding-bottom: 10px;
@@ -61,6 +96,8 @@
         right: 0px;
         padding: 5px 10px;
         color: var(--mk-sys-color);
+        height: var(--mk-tree-line-height);
+        line-height: var(--mk-tree-line-height);
       }
     }
   }
@@ -117,21 +154,22 @@
 .mk-tree-dropdown-wrap {
   box-shadow: 0 0 2px #bcbcbc;
   background: #ffffff;
-  min-width: 85px;
+  min-width: 100px;
   .button-list.toolbar-button {
     padding: 0px;
+    min-height: 36px;
     button {
       display: block;
       margin: 0!important;
       width: 100%;
       border-radius: 0px;
-      padding-left: 15px!important;
-      .anticon {
-        display: none;
-      }
-      .anticon + span {
-        margin-left: 0px;
-      }
+      border: 0px !important;
+      // color: rgba(0, 0, 0, 0.85)!important;
+      // background: transparent !important;
+      min-height: 36px;
+    }
+    button:not(:last-child) {
+      border-bottom: 1px solid #d8d8d8 !important;
     }
   }
 }
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 983d3c3..b56749d 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Row, Col, Modal } from 'antd'
+import moment from 'moment'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -41,6 +42,7 @@
 const AntvX6 = asyncComponent(() => import('./components/chart/antv-X6'))
 const Voucher = asyncComponent(() => import('./components/module/voucher'))
 const Account = asyncComponent(() => import('./components/module/account'))
+const Invoice = asyncComponent(() => import('./components/module/invoice'))
 const Iframe = asyncComponent(() => import('./components/iframe'))
 const Calendar = asyncComponent(() => import('./components/calendar'))
 const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
@@ -75,7 +77,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { MenuID, MenuName } = this.props
+    const { MenuID, MenuName, param } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -181,8 +183,8 @@
         try { // 閰嶇疆淇℃伅瑙f瀽
           let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
           if (userConfig) {
-            shortcuts = userConfig.action
-            userConfig.printers.forEach(item => {
+            shortcuts = userConfig.action || []
+            userConfig.printers && userConfig.printers.forEach(item => {
               window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
             })
           }
@@ -203,9 +205,18 @@
       let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
       let balMap = new Map()
       let skip = config.permission === 'false' || window.GLOB.mkHS
-      let param = this.props.param || {} // url鍙傛暟
+      let urlparam = {} // url鍙傛暟
+      if (param) {
+        Object.keys(param).forEach(key => {
+          if (/^\$/.test(key)) {
+            urlparam[key] = param[key]
+          } else {
+            urlparam[key.toLowerCase()] = param[key]
+          }
+        })
+      }
 
-      window.GLOB.CacheData.set(MenuID, param)
+      window.GLOB.CacheData.set(MenuID, urlparam)
 
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -223,7 +234,7 @@
       }
       if (config.urlFields) {
         config.urlFields.forEach(field => {
-          let val = `'${param[field] || ''}'`
+          let val = `'${urlparam[field.toLowerCase()] || ''}'`
           regs.push({
             reg: new RegExp('@' + field + '@', 'ig'),
             value: val
@@ -250,10 +261,10 @@
       let initInters = []
 
       config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters, config.MenuName)
-      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, urlparam, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
 
       let params = []
-      let BID = param.$BID || ''
+      let BID = urlparam.$BID || ''
       let inherit = {}
 
       if (config.cacheUseful === 'true') { // 缂撳瓨缁ф壙
@@ -265,18 +276,6 @@
       // 瀛楁閫忚
       config.components.forEach(component => {
         if (component.type !== 'search') return
-
-        if (param.$searchkey) {
-          component.search = component.search.map(item => {
-            if (['text', 'select', 'link', 'checkcard'].includes(item.type) && param.$searchkey === item.field) {
-              item.initval = param.$searchval
-            }
-  
-            return item
-          })
-
-          component.$searches = Utils.initMainSearch(component.search)
-        }
 
         window.GLOB.SearchBox.set(MenuID, component.$searches)
 
@@ -461,12 +460,7 @@
 
           if (item.setting.supModule === 'preview') {
             item.setting.supModule = ''
-            let val = ''
-            Object.keys(urlparam).forEach(key => {
-              if (key.toLowerCase() === item.setting.controlField) {
-                val = urlparam[key]
-              }
-            })
+            let val = urlparam[item.setting.controlField] || ''
 
             item.subtabs = item.subtabs.filter(tab => {
               if (tab.$pass) return true
@@ -479,12 +473,7 @@
         if (item.setting.selectField) {
           item.setting.selectField = item.setting.selectField.toLowerCase()
 
-          let val = ''
-          Object.keys(urlparam).forEach(key => {
-            if (key.toLowerCase() === item.setting.selectField) {
-              val = urlparam[key]
-            }
-          })
+          let val = urlparam[item.setting.selectField] || ''
 
           let activeKey = ''
 
@@ -565,8 +554,14 @@
         item.type = 'card'
       }
 
-      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
-        item.setting.supModule = item.supNodes[0].componentId
+      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗°�乼able澶氫笂绾х粍浠�
+        item.supNodes = item.supNodes.map(node => node.componentId)
+        if (item.supNodes[0]) {
+          item.setting.supModule = item.supNodes[0]
+        } else {
+          item.supNodes = null
+          item.setting.supModule = ''
+        }
       } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
         let pid = item.setting.supModule.pop()
         if (pid && pid !== 'empty') {
@@ -574,13 +569,33 @@
         } else {
           item.setting.supModule = ''
         }
+      } else if (item.type === 'search') {
+        if (item.wrap.supModule) {
+          item.wrap.supModule = item.wrap.supModule.pop()
+        }
       }
 
       // 鎼滅储鏉′欢鍒濆鍖�
       if (item.search) {
         Utils.initSearchVal(item)
 
+        if (urlparam.$searchkey) {
+          item.search.forEach(cell => {
+            if (urlparam.$searchkey === cell.field.toLowerCase() && ['text', 'select', 'link', 'checkcard'].includes(cell.type)) {
+              cell.initval = urlparam.$searchval
+            }
+          })
+        }
+
         item.$searches = Utils.initMainSearch(item.search)
+
+        if (item.type === 'search' && item.wrap.supModule) {
+          if (!item.checkBid) {
+            item.wrap.supModule = ''
+          } else {
+            window.GLOB.SearchBox.set(item.$searchId + 'checkBid', true)
+          }
+        }
       }
 
       let pass = skip
@@ -602,7 +617,7 @@
             cell = this.getPrinter(cell, item.uuid)
           }
 
-          return pass || permAction[cell.uuid]
+          return pass || permAction[cell.uuid] || cell.permission === 'false'
         })
       }
 
@@ -617,7 +632,10 @@
               col.type = 'custom'
             }
             
-            if (col.type === 'number') {
+            if (col.type === 'index') {
+              col.field = '$Index'
+              col.type = 'text'
+            } else if (col.type === 'number') {
               if (typeof(col.decimal) === 'number') {
                 col.round = Math.pow(10, col.decimal)
                 if (col.format === 'percent') {
@@ -644,7 +662,7 @@
                     cell = this.getPrinter(cell, item.uuid)
                   }
 
-                  return pass || permAction[cell.uuid]
+                  return pass || permAction[cell.uuid] || cell.permission === 'false'
                 } else {
                   cell = this.resetElement(cell)
                 }
@@ -672,6 +690,13 @@
         }
         
         item.cols = getCols(item.cols)
+
+        if (item.hasExtend) {
+          item.setting.hasExtend = true
+          item.setting.tableMode = 'compatible'
+          item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
+          item.colsCtrls = null
+        }
 
         if (item.subtype === 'editable') {
           item.submit.logLabel = item.$menuname + '-鎻愪氦'
@@ -707,7 +732,7 @@
               cell = this.resetElement(cell)
             }
 
-            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
+            return cell.eleType !== 'button' || pass || permAction[cell.uuid] || cell.permission === 'false'
           })
 
           if (card.setting.click === 'menus') {
@@ -749,7 +774,7 @@
               cell = this.resetElement(cell)
             }
 
-            return cell.eleType !== 'button' || pass || permAction[cell.uuid]
+            return cell.eleType !== 'button' || pass || permAction[cell.uuid] || cell.permission === 'false'
           })
         })
       } else if (item.type === 'balcony') {
@@ -773,7 +798,7 @@
             cell = this.resetElement(cell)
           }
 
-          return cell.eleType !== 'button' || pass || permAction[cell.uuid]
+          return cell.eleType !== 'button' || pass || permAction[cell.uuid] || cell.permission === 'false'
         })
       } else if (item.type === 'form') {
         item.subcards = item.subcards.map(group => {
@@ -945,7 +970,7 @@
     if (cell.syncComponentId) {
       if (cell.syncComponentId === item.setting.supModule) {
         cell.syncComponentId = ''
-        if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+        if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
           cell.execSuccess = 'mainline'
         }
       } else if (cell.syncComponentId === 'multiComponent') {
@@ -953,8 +978,17 @@
           return m.syncComId.pop() || ''
         })
 
-        if (item.setting.supModule && ids.includes(item.setting.supModule)) {
-          if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+        if (item.supNodes) {
+          item.supNodes.forEach(node => {
+            if (!ids.includes(node)) return
+
+            if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
+              cell.execSuccess = 'mainline'
+            }
+            ids = ids.filter(id => id !== node)
+          })
+        } else if (item.setting.supModule && ids.includes(item.setting.supModule)) {
+          if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
             cell.execSuccess = 'mainline'
           }
           ids = ids.filter(id => id !== item.setting.supModule)
@@ -980,6 +1014,17 @@
 
     if (cell.marks && cell.marks.length === 0) {
       cell.marks = null
+    }
+    if (cell.anchors && cell.anchors.length === 0) {
+      cell.anchors = null
+    }
+
+    if (cell.linkmenu && cell.linkmenu.length > 0) {
+      let menu_id = cell.linkmenu.pop()
+      cell.linkThdMenu = window.GLOB.mkThdMenus.get(menu_id) || ''
+      if (!cell.linkThdMenu) {
+        cell.link = ''
+      }
     }
 
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
@@ -1071,8 +1116,14 @@
       if (component.setting.useMSearch) {
         if (!window.GLOB.SearchBox.has(component.$searchId)) {
           component.setting.useMSearch = false
-        } else if (window.GLOB.SearchBox.has(component.$searchId + 'required')) {
-          component.$s_req = true
+        } else {
+          if (window.GLOB.SearchBox.has(component.$searchId + 'required')) {
+            component.$s_req = true
+          }
+          if (window.GLOB.SearchBox.has(component.$searchId + 'checkBid')) {
+            component.checkBid = true
+            component.setting.checkBid = true
+          }
         }
       }
 
@@ -1613,9 +1664,7 @@
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item}/>
-          </Col>
+          <NormalGroup config={item} style={style} key={item.uuid}/>
         )
       } else if (item.type === 'editor') {
         return (
@@ -1671,6 +1720,12 @@
             <Account config={item}/>
           </Col>
         )
+      } else if (item.type === 'module' && item.subtype === 'invoice') {
+        return (
+          <Col span={item.width} style={style} key={item.uuid}>
+            <Invoice config={item}/>
+          </Col>
+        )
       } else if (item.type === 'iframe') {
         return (
           <Col span={item.width} style={style} key={item.uuid}>
diff --git a/src/tabviews/custom/popview/index.jsx b/src/tabviews/custom/popview/index.jsx
index ca70341..4213bf9 100644
--- a/src/tabviews/custom/popview/index.jsx
+++ b/src/tabviews/custom/popview/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Row, Col, Modal } from 'antd'
+import moment from 'moment'
 
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
@@ -61,7 +62,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { Tab } = this.props
+    const { Tab, param } = this.props
 
     let config = Tab.config || ''
 
@@ -105,9 +106,18 @@
     // 鏉冮檺杩囨护
     let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
     let balMap = new Map()
-    let param = this.props.param || {} // url鍙傛暟
+    let urlparam = {} // url鍙傛暟
+    if (param) {
+      Object.keys(param).forEach(key => {
+        if (/^\$/.test(key)) {
+          urlparam[key] = param[key]
+        } else {
+          urlparam[key.toLowerCase()] = param[key]
+        }
+      })
+    }
 
-    window.GLOB.CacheData.set(Tab.uuid, param)
+    window.GLOB.CacheData.set(Tab.uuid, urlparam)
 
     let userName = sessionStorage.getItem('User_Name') || ''
     let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -129,23 +139,11 @@
       regs.push({ reg: /@works_flow_code@/ig, value: `'${flow.flow_code || ''}'` })
     }
 
-    config.components = this.filterComponent(config.components, roleId, balMap, param, Tab, Tab.uuid, Tab.uuid)
+    config.components = this.filterComponent(config.components, roleId, balMap, urlparam, Tab, Tab.uuid, Tab.uuid)
     
     // 鑾峰彇涓绘悳绱㈡潯浠�
     config.components.forEach(component => {
       if (component.type !== 'search') return
-
-      if (param.$searchkey) {
-        component.search = component.search.map(item => {
-          if (['text', 'select', 'link', 'checkcard'].includes(item.type) && param.$searchkey === item.field) {
-            item.initval = param.$searchval
-          }
-
-          return item
-        })
-
-        component.$searches = Utils.initMainSearch(component.search)
-      }
 
       window.GLOB.SearchBox.set(Tab.uuid, component.$searches)
 
@@ -155,7 +153,7 @@
     })
 
     let params = []
-    let BID = param.$BID || ''
+    let BID = urlparam.$BID || ''
 
     config.components = this.formatSetting(config.components, params, regs, balMap)
 
@@ -238,12 +236,7 @@
 
           if (item.setting.supModule === 'preview') {
             item.setting.supModule = ''
-            let val = ''
-            Object.keys(urlparam).forEach(key => {
-              if (key.toLowerCase() === item.setting.controlField) {
-                val = urlparam[key]
-              }
-            })
+            let val = urlparam[item.setting.controlField] || ''
 
             item.subtabs = item.subtabs.filter(tab => {
               if (tab.$pass) return true
@@ -256,12 +249,7 @@
         if (item.setting.selectField) {
           item.setting.selectField = item.setting.selectField.toLowerCase()
 
-          let val = ''
-          Object.keys(urlparam).forEach(key => {
-            if (key.toLowerCase() === item.setting.selectField) {
-              val = urlparam[key]
-            }
-          })
+          let val = urlparam[item.setting.selectField] || ''
 
           let activeKey = ''
 
@@ -326,8 +314,14 @@
         }
       }
 
-      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
-        item.setting.supModule = item.supNodes[0].componentId
+      if (item.wrap && item.wrap.supType === 'multi') { // 鏁版嵁鍗°�乼able澶氫笂绾х粍浠�
+        item.supNodes = item.supNodes.map(node => node.componentId)
+        if (item.supNodes[0]) {
+          item.setting.supModule = item.supNodes[0]
+        } else {
+          item.supNodes = null
+          item.setting.supModule = ''
+        }
       } else if (item.setting && item.setting.supModule && typeof(item.setting.supModule) !== 'string') {
         let pid = item.setting.supModule.pop()
         if (pid && pid !== 'empty') {
@@ -367,7 +361,10 @@
               col.type = 'custom'
             }
             
-            if (col.type === 'number') {
+            if (col.type === 'index') {
+              col.field = '$Index'
+              col.type = 'text'
+            } else if (col.type === 'number') {
               if (typeof(col.decimal) === 'number') {
                 col.round = Math.pow(10, col.decimal)
                 if (col.format === 'percent') {
@@ -417,6 +414,13 @@
         }
         
         item.cols = getCols(item.cols)
+
+        if (item.hasExtend) {
+          item.setting.hasExtend = true
+          item.setting.tableMode = 'compatible'
+          item.setting.extendTime = moment().format('YYYY-MM-DD HH:mm:ss')
+          item.colsCtrls = null
+        }
 
         if (item.subtype === 'editable') {
           item.submit.logLabel = item.$menuname + '-鎻愪氦'
@@ -663,7 +667,7 @@
     if (cell.syncComponentId) {
       if (cell.syncComponentId === item.setting.supModule) {
         cell.syncComponentId = ''
-        if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+        if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
           cell.execSuccess = 'mainline'
         }
       } else if (cell.syncComponentId === 'multiComponent') {
@@ -671,8 +675,17 @@
           return m.syncComId.pop() || ''
         })
 
-        if (item.setting.supModule && ids.includes(item.setting.supModule)) {
-          if (cell.execSuccess === 'line' || cell.execSuccess === 'grid') {
+        if (item.supNodes) {
+          item.supNodes.forEach(node => {
+            if (!ids.includes(node)) return
+
+            if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
+              cell.execSuccess = 'mainline'
+            }
+            ids = ids.filter(id => id !== node)
+          })
+        } else if (item.setting.supModule && ids.includes(item.setting.supModule)) {
+          if (['line', 'grid', 'line_grid'].includes(cell.execSuccess)) {
             cell.execSuccess = 'mainline'
           }
           ids = ids.filter(id => id !== item.setting.supModule)
@@ -698,6 +711,17 @@
 
     if (cell.marks && cell.marks.length === 0) {
       cell.marks = null
+    }
+    if (cell.anchors && cell.anchors.length === 0) {
+      cell.anchors = null
+    }
+
+    if (cell.linkmenu && cell.linkmenu.length > 0) {
+      let menu_id = cell.linkmenu.pop()
+      cell.linkThdMenu = window.GLOB.mkThdMenus.get(menu_id) || ''
+      if (!cell.linkThdMenu) {
+        cell.link = ''
+      }
     }
 
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
@@ -1121,9 +1145,7 @@
         )
       } else if (item.type === 'group' && item.subtype === 'normalgroup') {
         return (
-          <Col span={item.width} style={style} key={item.uuid}>
-            <NormalGroup config={item}/>
-          </Col>
+          <NormalGroup config={item} style={style} key={item.uuid}/>
         )
       } else if (item.type === 'editor') {
         return (
diff --git a/src/tabviews/debugtable/index.jsx b/src/tabviews/debugtable/index.jsx
index 9f52daa..155332e 100644
--- a/src/tabviews/debugtable/index.jsx
+++ b/src/tabviews/debugtable/index.jsx
@@ -44,6 +44,8 @@
 
     let param = UtilsDM.getQueryDataParams(setting, [], 'sort', 1, 50, '')
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
 
     if (result.status) {
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index c10bc79..39cbb1d 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -221,6 +221,7 @@
 
       let _actions = []     // 宸ュ叿鏍忔寜閽�
       let _operations = []  // 鎿嶄綔鍒楁寜閽紙瀛樺湪鏃讹級
+      let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#E7E7EF', default: 'rgba(0, 0, 0, 0.65)' }
 
       config.action.forEach(item => {
         item.logLabel = Tab.label + '-' + item.label // 鐢ㄤ簬sPC_TableData_InUpDe璁板綍鎿嶄綔鎸夐挳
@@ -270,10 +271,25 @@
           }
         }
         
+        item.show = 'button'
+
+        let _c = item.class ? item.class.replace('border-', '') : ''
+        let color = colors[_c] || '#1890ff'
+
         if (item.position === 'toolbar') {
           item.$toolbtn = true
+
+          if (item.class === 'default') {
+            item.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: '#fff', borderColor: '#d9d9d9', marginRight: '15px'}
+          } else if (item.class.indexOf('border') > -1) {
+            item.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
+          } else {
+            item.style = {color: item.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+          }
+
           _actions.push(item)
         } else if (item.position === 'grid') {
+          item.style = {color: color, backgroundColor: 'transparent', borderColor: 'transparent'}
           _operations.push(item)
         }
       })
@@ -464,6 +480,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
 
     this.getStatFieldsValue(searches)
@@ -550,6 +568,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index 8ba9910..bc3c2db 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -192,6 +192,7 @@
 
       let _actions = []     // 宸ュ叿鏍忔寜閽�
       let _operations = []  // 鎿嶄綔鍒楁寜閽紙瀛樺湪鏃讹級
+      let colors = { primary: '#1890ff', yellow: '#c49f47', orange: 'orange', danger: '#ff4d4f', green: '#26C281', dgreen: '#32c5d2', purple: '#8E44AD', cyan: '#13c2c2', gray: '#E7E7EF', default: 'rgba(0, 0, 0, 0.65)' }
 
       config.action.forEach(item => {
         item.logLabel = Tab.label + '-' + item.label // 鐢ㄤ簬sPC_TableData_InUpDe璁板綍鎿嶄綔鎸夐挳
@@ -228,10 +229,25 @@
           }
         }
 
+        item.show = 'button'
+
+        let _c = item.class ? item.class.replace('border-', '') : ''
+        let color = colors[_c] || '#1890ff'
+
         if (item.position === 'toolbar') {
           item.$toolbtn = true
+
+          if (item.class === 'default') {
+            item.style = {color: 'rgba(0, 0, 0, 0.65)', backgroundColor: '#fff', borderColor: '#d9d9d9', marginRight: '15px'}
+          } else if (item.class.indexOf('border') > -1) {
+            item.style = {color: color, backgroundColor: '#fff', borderColor: color, marginRight: '15px'}
+          } else {
+            item.style = {color: item.class === 'gray' ? 'rgba(0, 0, 0, 0.65)' : '#fff', backgroundColor: color, borderColor: color, marginRight: '15px'}
+          }
+
           _actions.push(item)
         } else if (item.position === 'grid') {
+          item.style = {color: color, backgroundColor: 'transparent', borderColor: 'transparent'}
           _operations.push(item)
         }
       })
@@ -398,6 +414,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
 
     this.getStatFieldsValue(searches)
@@ -523,6 +541,8 @@
     let _orderBy = orderBy || setting.order
     let param = UtilsDM.getQueryDataParams(setting, searches, _orderBy, pageIndex, pageSize, BID, id)
 
+    delete param.s_version_up
+
     let result = await Api.genericInterface(param)
     if (result.status) {
       let data = fromJS(this.state.data).toJS()
diff --git a/src/tabviews/treepage/index.jsx b/src/tabviews/treepage/index.jsx
index 00b7d2f..a4c89ae 100644
--- a/src/tabviews/treepage/index.jsx
+++ b/src/tabviews/treepage/index.jsx
@@ -78,8 +78,8 @@
         try { // 閰嶇疆淇℃伅瑙f瀽
           let userConfig = JSON.parse(window.decodeURIComponent(window.atob(result.LongParamUser)))
           if (userConfig) {
-            shortcuts = userConfig.action
-            userConfig.printers.forEach(item => {
+            shortcuts = userConfig.action || []
+            userConfig.printers && userConfig.printers.forEach(item => {
               window.GLOB.UserCacheMap.set(item.parentId + item.uuid, item)
             })
           }
@@ -265,6 +265,8 @@
 
     let param = UtilsDM.getQueryDataParams(setting, [], setting.order, '', '', BID)
 
+    delete param.s_version_up
+    
     let result = await Api.genericInterface(param)
     if (result.status) {
       let parentNodes = []
diff --git a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
index d70ca80..a85c8a0 100644
--- a/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/changeuserbutton/index.jsx
@@ -102,12 +102,13 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { setting, selectedData, btn, MenuID } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { setting, selectedData, btn, MenuID, LID } = this.props
     const { loading, disabled } = this.state
     
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
 
     if (btn.funcType === 'closetab') {
       MKEmitter.emit('closeTabView', MenuID || btn.$MenuID)
@@ -115,8 +116,6 @@
       if (btn.refreshTab && btn.refreshTab.length > 0) {
         MKEmitter.emit('reloadMenuView', btn.refreshTab[btn.refreshTab.length - 1], 'table')
       }
-      return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
       return
     }
     
@@ -228,38 +227,23 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return (
       <Button
-        type={type}
+        type="link"
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
         style={btn.style}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/editLine/index.jsx b/src/tabviews/zshare/actionList/editLine/index.jsx
index 142d977..90f053d 100644
--- a/src/tabviews/zshare/actionList/editLine/index.jsx
+++ b/src/tabviews/zshare/actionList/editLine/index.jsx
@@ -109,37 +109,22 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <MkIcon type={btn.icon} />
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return (
       <Button
-        type={type}
+        type="link"
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         disabled={disabled}
         style={btn.style}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
index bfc7d78..ab1cc80 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -106,12 +106,15 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { setting, BID, btn, selectedData } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { setting, BID, btn, selectedData, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
+
+    let data = record || selectedData || []
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -119,44 +122,35 @@
         message: '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
-      return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
-
-    let data = record || selectedData || []
-    
-    if (btn.Ot === 'requiredSgl' && data.length !== 1) {
+    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
         message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
         duration: 5
       })
-      return
     } else if (!btn.verify || !btn.verify.sheet || !btn.verify.columns || btn.verify.columns.length === 0) {
       notification.warning({
         top: 92,
         message: 'excel瀵煎叆楠岃瘉淇℃伅鏈缃紒',
         duration: 5
       })
-      return
-    }
-
-    let primaryId = '' // 瀵煎叆鏃惰Id
-    if (btn.Ot === 'requiredSgl' && setting.primaryKey) {
-      primaryId = data[0][setting.primaryKey] || ''
-    }
-
-    this.setState({
-      selines: data,
-      primaryId: primaryId
-    }, () => {
-      this.refs.excelIn.exceltrigger()
-    })
-
-    if (window.GLOB.systemType === 'production') {
-      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎叆Excel'})
+    } else {
+      let primaryId = '' // 瀵煎叆鏃惰Id
+      if (btn.Ot === 'requiredSgl' && setting.primaryKey) {
+        primaryId = data[0][setting.primaryKey] || ''
+      }
+  
+      this.setState({
+        selines: data,
+        primaryId: primaryId
+      }, () => {
+        this.refs.excelIn.exceltrigger()
+      })
+  
+      if (window.GLOB.systemType === 'production') {
+        MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎叆Excel'})
+      }
     }
   }
 
@@ -408,6 +402,9 @@
         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) {
@@ -534,39 +531,24 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || 'upload'
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return <>
       <Button
-        type={type}
+        type="link"
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
         style={btn.style}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
       <ExcelIn btn={btn} triggerExcelIn={() => this.setState({ loading: true })} returndata={this.getexceldata} ref="excelIn" />
diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
index 5db6635..0317ad6 100644
--- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -90,12 +90,13 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { setting, BID, btn } = this.props
+  actionTrigger = (triggerId, _, type, lid) => {
+    const { setting, BID, btn, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -103,30 +104,23 @@
         message: '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
-      return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(this.props.selectedData || []), fromJS(record))) {
-      return
-    }
-
-    if (btn.errorType === 'error1') {
+    } else if (btn.errorType === 'error1') {
       notification.warning({
         top: 92,
         message: '璇疯缃鍑哄垪锛�',
         duration: 5
       })
-      return
     } else if (btn.errorType === 'error2') {
       notification.warning({
         top: 92,
         message: '鎸夐挳闇�鑷畾涔夊鍑烘暟鎹簮锛�',
         duration: 5
       })
-      return
-    }
-
-    MKEmitter.emit('queryModuleParam', btn.$menuId, this.triggerExcelout)
-    if (window.GLOB.systemType === 'production') {
-      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎嚭Excel'})
+    } else {
+      MKEmitter.emit('queryModuleParam', btn.$menuId, this.triggerExcelout)
+      if (window.GLOB.systemType === 'production') {
+        MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '瀵煎嚭Excel'})
+      }
     }
   }
 
@@ -183,6 +177,9 @@
         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(result => {
@@ -387,6 +384,9 @@
         param.username = sessionStorage.getItem('User_Name') || ''
         param.fullname = sessionStorage.getItem('Full_Name') || ''
       }
+      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)
@@ -443,23 +443,70 @@
   /**
    * @description Excel 鐢熸垚
    */
-  exportExcel = (data, ErrCode, msg, search) => {
+  exportExcel = (data = [], ErrCode, msg, search) => {
     const { btn } = this.props
     
     let imgCol = false
-    let columns = btn.verify.columns.map(col => {
+    let merge = false
+    let styles = []
+    let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+    let columns = btn.verify.columns.map((col, index) => {
       if (col.type === 'image') {
         imgCol = true
       }
+      if (btn.verify.merge === 'true' && /.+-.+/.test(col.Text)) {
+        merge = true
+      }
 
-      if (col.type === 'number' && (col.decimal || col.decimal === 0) ) {
-        col.round = Math.pow(10, col.decimal)
+      let i = Math.floor(index / 26)
+      let s = letters[i - 1] || ''
+      col.name = s + letters[index % 26]
+
+      if (col.type === 'number') {
+        if (col.decimal || col.decimal === 0) {
+          col.round = Math.pow(10, col.decimal)
+
+          if (col.format) {
+            let dec = Array(col.decimal).fill(0).join('')
+            dec = dec ? '.' + dec : ''
+            if (col.format === 'thdSeparator') {
+              col.z = '#,##0' + dec
+            } else if (col.format === 'thdSepPm') {
+              col.z = '#,##0' + dec + ';'
+              col.z = col.z + '[Red]-' + col.z
+            } else if (col.format === 'percent') {
+              let _dec = ''
+              if (col.decimal > 2) {
+                Array(col.decimal - 2).fill(0).join('')
+                _dec = _dec ? '.' + _dec : ''
+              }
+
+              col.z = '0' + _dec + '%'
+            }
+          }
+        }
+      } else if (col.type === 'text') {
+        if (col.wrapText === 'true') {
+          col.s = {alignment: { wrapText: true }}
+        }
+        if (col.textFormat) {
+          if (col.textFormat === 'YYYY-MM-DD') {
+            col.z = 'yyyy-mm-dd;@'
+          } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss') {
+            col.z = 'yyyy-mm-dd hh:mm:ss'
+          }
+        }
+      }
+
+      if (col.z || col.s) {
+        styles.push(col)
       }
 
       return col
     })
 
-    if (data && data[0]) {
+    if (data[0]) {
       let errors = []
       columns.forEach(col => {
         if (col.output === 'false') return
@@ -508,7 +555,7 @@
 
         let table = []
 
-        data && data.forEach((item, index) => {
+        data.forEach((item, index) => {
           let _row = {}
   
           item.$Index = index + 1 + ''
@@ -516,21 +563,48 @@
           columns.forEach((col, i) => {
             let val = item[col.Column]
             if (col.output === 'false') {
-              if (col.type === 'number') {
+              if (col.type === 'number' && col.noValue !== 'false') {
                 val = 0
               } else {
                 val = ''
               }
-            } else if (col.type === 'number' && typeof(val) === 'number') {
-              if (col.abs === 'true') {
-                val = Math.abs(val)
+            } else if (col.type === 'number') {
+              if (val && typeof(val) === 'string' && !isNaN(val)) {
+                val = +val
               }
-              if (col.round) {
-                val = Math.round(val * col.round) / col.round
-                // val = val.toFixed(col.decimal)
+              if (typeof(val) === 'number') {
+                if (col.abs === 'true') {
+                  val = Math.abs(val)
+                }
+                if (col.round) {
+                  val = Math.round(val * col.round) / col.round
+                }
+                if (col.noValue === 'false' && val === 0) {
+                  val = ''
+                }
               }
-              if (col.noValue === 'false' && val === 0) {
+            } else if (col.type === 'text') {
+              val = val + ''
+              
+              if (col.textFormat) {
+                if (col.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(val)) {
+                  val = `${val.substr(0, 4)}-${val.substr(5, 2)}-${val.substr(8, 2)}`
+                } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(val)) {
+                  val = `${val.substr(0, 4)}-${val.substr(5, 2)}-${val.substr(8, 2)} ${val.substr(11, 2)}:${val.substr(14, 2)}:${val.substr(17, 2)}`
+                }
+              }
+
+              if (col.noValue === 'false' && val < '1949-10-02') {
                 val = ''
+              }
+            }
+
+            if (val !== '') {
+              if (col.prefix) {
+                val = col.prefix + val
+              }
+              if (col.postfix) {
+                val = val + col.postfix
               }
             }
 
@@ -544,16 +618,6 @@
 
         this.execSuccess({ErrCode: ErrCode || 'S', message: msg || '瀵煎嚭鎴愬姛锛�'})
       } else {
-        let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-        let cols = []
-
-        for (let index = 0; index < columns.length; index++) {
-          let i = Math.floor(index / 26)
-          let s = letters[i - 1] || ''
-          
-          cols.push(s + letters[index % 26])
-        }
-
         let table = []
         let _header = []
         let _topRow = {}
@@ -561,16 +625,16 @@
         let requires = []
         let merges = []
 
-        columns.forEach((col, i) => {
+        columns.forEach(col => {
           _header.push(col.Column)
           _topRow[col.Column] = col.Text
           colwidth.push({wch: col.Width || 20})
           if (col.required === 'true') {
-            requires.push(i)
+            requires.push(col.name)
           }
         })
 
-        if (btn.verify.merge === 'true') {
+        if (merge) {
           let fLine = {}
           let sLine = {}
           let sign = ''
@@ -582,16 +646,16 @@
               sLine[col.Column] = _name
 
               if (sign === _sign) {
-                merges[merges.length - 1] = merges[merges.length - 1].split(':')[0] + `:${cols[i]}1`
+                merges[merges.length - 1] = merges[merges.length - 1].split(':')[0] + `:${col.name}1`
               } else {
-                merges.push(`${cols[i]}1:${cols[i]}2`)
+                merges.push(`${col.name}1:${col.name}2`)
                 sign = _sign
               }
             } else {
               fLine[col.Column] = col.Text
               sLine[col.Column] = col.Text
               sign = ''
-              merges.push(`${cols[i]}1:${cols[i]}2`)
+              merges.push(`${col.name}1:${col.name}2`)
             }
           })
 
@@ -601,7 +665,7 @@
           table.push(_topRow)
         }
   
-        data && data.forEach((item, index) => {
+        data.forEach((item, index) => {
           let _row = {}
   
           item.$Index = index + 1 + ''
@@ -610,21 +674,48 @@
             let val = item[col.Column]
 
             if (col.output === 'false') {
-              if (col.type === 'number') {
+              if (col.type === 'number' && col.noValue !== 'false') {
                 val = 0
               } else {
                 val = ''
               }
-            } else if (col.type === 'number' && typeof(val) === 'number') {
-              if (col.abs === 'true') {
-                val = Math.abs(val)
+            } else if (col.type === 'number') {
+              if (val && typeof(val) === 'string' && !isNaN(val)) {
+                val = +val
               }
-              if (col.round) {
-                val = Math.round(val * col.round) / col.round
-                // val = val.toFixed(col.decimal)
+              if (typeof(val) === 'number') {
+                if (col.abs === 'true') {
+                  val = Math.abs(val)
+                }
+                if (col.round) {
+                  val = Math.round(val * col.round) / col.round
+                }
+                if (col.noValue === 'false' && val === 0) {
+                  val = ''
+                }
               }
-              if (col.noValue === 'false' && val === 0) {
+            } else if (col.type === 'text') {
+              val = val + ''
+              
+              if (col.textFormat) {
+                if (col.textFormat === 'YYYY-MM-DD' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1])/.test(val)) {
+                  val = `${val.substr(0, 4)}-${val.substr(5, 2)}-${val.substr(8, 2)}`
+                } else if (col.textFormat === 'YYYY-MM-DD HH:mm:ss' && /^[1-9]\d{3}(-|\/)(0[1-9]|1[0-2])(-|\/)(0[1-9]|[1-2][0-9]|3[0-1]).([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/.test(val)) {
+                  val = `${val.substr(0, 4)}-${val.substr(5, 2)}-${val.substr(8, 2)} ${val.substr(11, 2)}:${val.substr(14, 2)}:${val.substr(17, 2)}`
+                }
+              }
+
+              if (col.noValue === 'false' && val < '1949-10-02') {
                 val = ''
+              }
+            }
+
+            if (val !== '') {
+              if (col.prefix) {
+                val = col.prefix + val
+              }
+              if (col.postfix) {
+                val = val + col.postfix
               }
             }
 
@@ -644,49 +735,46 @@
 
         if (requires.length) {
           requires.forEach(col => {
-            if (cols[col]) {
-              ws[cols[col] + '1'].s = {font: { color: { rgb: 'F5222D' } }}
-            }
+            ws[col + '1'].s = {font: { color: { rgb: 'F5222D' } }}
           })
         }
 
-        if (merges.length) {
+        if (merge) {
           ws['!merges'] = []
           merges.forEach(item => {
             ws['!merges'].push(XLSX.utils.decode_range(item))
           })
 
-          cols.forEach(col => {
-            if (ws[col + '1'].s) {
-              ws[col + '1'].s = {font: { color: { rgb: 'F5222D' } }, alignment: { horizontal: 'center', vertical: 'center' }}
-            } else {
-              ws[col + '1'].s = {alignment: { horizontal: 'center', vertical: 'center' }}
-            }
-            ws[col + '2'].s = {alignment: { horizontal: 'center', vertical: 'center' }}
+          columns.forEach(col => {
+            ws[col.name + '1'].s = ws[col.name + '1'].s || {}
+            ws[col.name + '1'].s.alignment = { horizontal: 'center', vertical: 'center' }
+
+            ws[col.name + '2'].s = {alignment: { horizontal: 'center', vertical: 'center' }}
           })
         }
 
-        if (btn.verify.wrapText === 'true' && data) {
-          let lines = data.length + 1
-          let start = 2
-          if (btn.verify.merge === 'true') {
-            lines = data.length + 2
-          }
-          for (let n = 0; n < cols.length; n++) {
-            for (let m = start; m <= lines; m++) {
-              if (ws[cols[n] + m] && !ws[cols[n] + m].s) {
-                ws[cols[n] + m].s = {alignment: { wrapText: true }}
+        // ws['A3'].s = {font: { sz: 10 , bold: true }, alignment: { horizontal: 'center', vertical: 'center' }, border: {top: {style: 'thin', color: '000000'}, left: {style: 'thin', color: '000000'}, bottom: {style: 'thin', color: '000000'}, right: {style: 'thin', color: '000000'}}};
+        // ws['A3'].z = '#,##0.00';
+        // ws['A3'].z = '#,##0.00;[Red]-#,##0.00;';
+        // ws["A1"].s = {fill: { bgColor: { rgb: "FFFFAA"  }}, font: { color: { rgb: "1890FF" } }}
+
+        if (data.length && styles.length) {
+          for (let n = table.length - data.length + 1; n <= table.length; n++) {
+            styles.forEach(col => {
+              if (col.z) {
+                ws[col.name + n].z = col.z
               }
-            }
+              if (col.s) {
+                ws[col.name + n].s = col.s
+              }
+            })
           }
         }
-
-        // ws["A1"].s = {fill: { bgColor: { rgb: "FFFFAA"  }}, font: { color: { rgb: "1890FF" } }}
 
         const wb = XLSX.utils.book_new()
         XLSX.utils.book_append_sheet(wb, ws, btn.verify.sheet || 'Sheet1')
   
-        XLSX.writeFile(wb, `${btn.$menuName || ''}${moment().format('YYYYMMDDHHmmss')}.xlsx`)
+        XLSX.writeFile(wb, `${btn.verify.excelName || btn.$menuName || ''}${moment().format('YYYYMMDDHHmmss')}.xlsx`)
   
         this.execSuccess({ErrCode: ErrCode || 'S', message: msg || '瀵煎嚭鎴愬姛锛�'})
       }
@@ -784,9 +872,9 @@
       _setting.arr_field = []
 
       btn.verify.columns.forEach(col => {
-        if (col.Column && col.Column !== '$Index') {
-          _setting.arr_field.push(col.Column)
-        }
+        if (col.output === 'false' || !col.Column || col.Column === '$Index') return
+        
+        _setting.arr_field.push(col.Column)
       })
       _setting.arr_field = _setting.arr_field.join(',')
       _setting.execute = btn.verify.defaultSql !== 'false'
@@ -986,39 +1074,24 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || 'download'
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return (
       <Button
-        type={type}
+        type="link"
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
         style={btn.style || null}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/exportPdf/index.jsx b/src/tabviews/zshare/actionList/exportPdf/index.jsx
index 8a8ad2e..89575fe 100644
--- a/src/tabviews/zshare/actionList/exportPdf/index.jsx
+++ b/src/tabviews/zshare/actionList/exportPdf/index.jsx
@@ -109,42 +109,28 @@
     const { btn } = this.props
     const { loading } = this.state
 
-    let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
     let style = {...btn.style}
 
     if (loading) {
       style.opacity = 0
     }
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    let label = ''
+
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <MkIcon type={btn.icon} />
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
     
     return (
       <Button
-        type={type}
+        type="link"
         title={btn.show === 'icon' ? btn.label : ''}
         style={style}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/funcMegvii/index.jsx b/src/tabviews/zshare/actionList/funcMegvii/index.jsx
index 78adb47..652dc2a 100644
--- a/src/tabviews/zshare/actionList/funcMegvii/index.jsx
+++ b/src/tabviews/zshare/actionList/funcMegvii/index.jsx
@@ -108,12 +108,16 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { BID, btn, selectedData, setting } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { BID, btn, selectedData, setting, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
+
+    let data = record || selectedData || []
+    // let data = fromJS(mockdata.data).toJS()
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -121,29 +125,20 @@
         message: '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
-      return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
-
-    let data = record || selectedData || []
-    // let data = fromJS(mockdata.data).toJS()
-    
-    if (data.length === 0) {
+    } else if (data.length === 0) {
       // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
       notification.warning({
         top: 92,
         message: '璇烽�夋嫨琛岋紒',
         duration: 5
       })
-      return
+    } else {
+      this.setState({
+        loading: true,
+        lines: data
+      })
+      this.getIpList()
     }
-
-    this.setState({
-      loading: true,
-      lines: data
-    })
-    this.getIpList()
   }
 
   getIpList = () => {
@@ -514,43 +509,26 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
+    } else if (btn.$toolbtn) {
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{loadingNumber && !loadingTotal ? `(${loadingNumber})` : ''}{btn.label}</span>
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
-    }
-    
-    if (loadingNumber && !loadingTotal && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
-      label = (loadingNumber && !loadingTotal ? `(${loadingNumber})` : '') + btn.label
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return (
       <>
         <Button
-          type={type}
+          type="link"
           title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
           loading={loading}
           disabled={disabled}
           style={btn.style}
-          icon={icon}
-          className={className}
+          className={btn.hover || ''}
           onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
         >{label}</Button>
         {this.getModels()}
diff --git a/src/tabviews/zshare/actionList/funcbutton/index.jsx b/src/tabviews/zshare/actionList/funcbutton/index.jsx
new file mode 100644
index 0000000..cf887d2
--- /dev/null
+++ b/src/tabviews/zshare/actionList/funcbutton/index.jsx
@@ -0,0 +1,344 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Button, notification, message, Modal } from 'antd'
+import md5 from 'md5'
+
+import Api from '@/api'
+import MKEmitter from '@/utils/events.js'
+import MkIcon from '@/components/mk-icon'
+
+// import './index.scss'
+const { confirm } = Modal
+
+class FuncButton extends Component {
+  static propTpyes = {
+    BID: PropTypes.string,
+    btn: PropTypes.object,
+    selectedData: PropTypes.any,
+    disabled: PropTypes.any
+  }
+
+  state = {
+    loading: false,
+    disabled: false,
+    hidden: false,
+  }
+
+  UNSAFE_componentWillMount () {
+    const { btn, selectedData, BData, disabled } = this.props
+
+    if (btn.controlField) {
+      this.setStatus(btn, selectedData || [], BData, disabled)
+    } else if (disabled) {
+      this.setState({disabled: true})
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { btn } = this.props
+
+    if (btn.controlField) {
+      this.setStatus(btn, nextProps.selectedData || [], nextProps.BData, nextProps.disabled)
+    } else {
+      this.setState({disabled: nextProps.disabled === true})
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
+  }
+
+  setStatus = (btn, data, BData, disprop) => {
+    let disabled = false
+    let hidden = false
+
+    if (btn.control !== 'parent') {
+      if (data.length > 0) {
+        data.forEach(item => {
+          let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
+          if (btn.controlVals.includes(s)) {
+            disabled = true
+          }
+        })
+      } else if (btn.controlVals.includes('')) {
+        disabled = true
+      }
+    } else {
+      if (!BData || !BData.hasOwnProperty(btn.controlField)) {
+        hidden = true
+      } else {
+        let s = BData[btn.controlField] + ''
+        if (btn.controlVals.includes(s)) {
+          hidden = true
+        }
+      }
+    }
+
+    if (disabled && btn.control === 'hidden') {
+      hidden = true
+    }
+
+    if (disprop) {
+      disabled = true
+    }
+
+    this.setState({hidden, disabled})
+  }
+
+  /**
+   * @description 瑙﹀彂鎸夐挳鎿嶄綔
+   */
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { btn, BID, selectedData, LID } = this.props
+    const { loading } = this.state
+
+    if (loading) return
+    if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
+
+    let data = record || selectedData || []
+    let error = ''
+
+    if (btn.funcType === 'shareLink' && window.GLOB.systemType === 'production' && !btn.shareProUrl) {
+      error = '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�'
+    } else if (btn.funcType === 'refund') {
+      if (data.length === 0) {
+        error = '璇烽�夋嫨琛岋紒'
+      } else if (data.length !== 1) {
+        error = '璇烽�夋嫨鍗曡鏁版嵁锛�'
+      } else if (!data[0].$$uuid) {
+        error = '鏈幏鍙栧埌璁㈠崟缂栧彿锛�'
+      }
+    }
+
+    if (error) {
+      notification.warning({
+        top: 92,
+        message: error,
+        duration: 5
+      })
+      return
+    }
+
+    if (btn.funcType === 'shareLink') {
+      let bid = BID || ''
+      let id = ''
+      if (data[0]) {
+        id = data[0].$$uuid || ''
+      }
+  
+      let url = btn.shareUrl
+      if (window.GLOB.systemType === 'production') {
+        url = btn.shareProUrl
+      }
+  
+      url = url.replace(/@BID@/ig, bid).replace(/@ID@/ig, id)
+  
+      if (btn.shortUrl === 'true') {
+        this.setState({
+          loading: true
+        }, () => {
+          this.getShortUrl(url)
+        })
+      } else {
+        this.copyUrl(url)
+      }
+    } else if (btn.funcType === 'refund') {
+      let orderId = data[0].$$uuid
+      const that = this
+
+      confirm({
+        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        onOk() {
+          that.execRefund(orderId)
+        },
+        onCancel() {}
+      })
+    }
+  }
+
+  execRefund = (orderId) => {
+    Api.setRefund(orderId).then(res => {
+      if (!res.status) {
+        this.execError({ErrCode: 'E', message: '鎵ц澶辫触锛�', ...res})
+      } else {
+        this.execSuccess({ErrCode: 'S', ...res})
+      }
+    })
+  }
+
+  getShortUrl = (url) => {
+    let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
+    let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
+
+    let param = {
+      func: 's_url_db_adduptdel',
+      appkey: window.GLOB.appkey,
+      userid: _id,
+      LoginUID: _id,
+      type: 'add_only',
+      validity: 15,
+      linkurl: url,
+      nonc: '' + new Date().getTime(),
+      id: md5(url + window.GLOB.appkey)
+    }
+
+    let keys = Object.keys(param).sort()
+    let values = ''
+    keys.forEach(key => {
+      values += key + param[key]
+    })
+    param.sign = md5(values)
+    param.t = new Date().getTime()
+
+    Api.directRequest({
+      url: _rduri + '/s_url_db_adduptdel',
+      method: 'post',
+      data: JSON.stringify(param)
+    }).then(res => {
+      this.setState({
+        loading: false
+      })
+
+      if (res.status && res.id) {
+        this.copyUrl('https://mk9h.cn/m.asp?m=' + res.id)
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message || '閾炬帴鐢熸垚澶辫触锛�',
+          duration: 5
+        })
+      }
+    }, () => {
+      this.setState({
+        loading: false
+      })
+    })
+  }
+
+  copyUrl = (url) => {
+    const { btn } = this.props
+
+    let oInput = document.createElement('input')
+    oInput.value = url
+    document.body.appendChild(oInput)
+    oInput.select()
+    document.execCommand('Copy')
+    document.body.removeChild(oInput)
+
+    if (btn.shareTip) {
+      Modal.success({
+        title: btn.shareTip
+      })
+    } else {
+      message.success('宸插鍒跺埌鍓垏鏉裤��')
+    }
+  }
+
+  execSuccess = (res = {}) => {
+    const { btn } = this.props
+
+    if (res.ErrCode === 'S' || !res.ErrCode) { // 鎵ц鎴愬姛
+      notification.success({
+        top: 92,
+        message: res.message || '鎵ц鎴愬姛锛�',
+        duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
+      })
+    } else if (res.ErrCode === 'Y') { // 鎵ц鎴愬姛
+      Modal.success({
+        title: res.message || '鎵ц鎴愬姛锛�'
+      })
+    } else if (res.ErrCode === '-1') { // 瀹屾垚鍚庝笉鎻愮ず
+
+    }
+
+    this.setState({
+      loading: false
+    })
+
+    if (btn.execSuccess !== 'never') {
+      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
+    }
+  }
+
+  execError = (res) => {
+    const { btn } = this.props
+
+    if (!['LoginError', 'C', '-2', 'E', 'N', 'F', 'NM'].includes(res.ErrCode)) {
+      res.ErrCode = 'E'
+    }
+
+    if (res.ErrCode === 'E') {
+      Modal.error({
+        title: res.message || '鎵ц澶辫触锛�',
+      })
+    } else if (res.ErrCode === 'N') {
+      notification.error({
+        top: 92,
+        message: res.message || '鎵ц澶辫触锛�',
+        duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
+      })
+    } else if (res.ErrCode === 'F') {
+      notification.error({
+        className: 'notification-custom-error',
+        top: 92,
+        message: res.message || '鎵ц澶辫触锛�',
+        duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
+      })
+    } else if (res.ErrCode === 'NM') {
+      message.error(res.message || '鎵ц澶辫触锛�')
+    }
+    
+    this.setState({
+      loading: false
+    })
+
+    if (res.ErrCode === '-2') return
+
+    if (btn.execError !== 'never') {
+      MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
+    }
+  }
+
+  render() {
+    const { btn } = this.props
+    const { loading, hidden } = this.state
+
+    if (hidden) return null
+
+    let label = ''
+
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
+    } else if (btn.show === 'icon') {
+      label = !loading ? <MkIcon type={btn.icon} /> : null
+    } else {
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
+    }
+    
+    return (
+      <Button
+        type="link"
+        title={btn.show === 'icon' ? btn.label : ''}
+        loading={loading}
+        style={btn.style || null}
+        className={btn.hover || ''}
+        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
+      >{label}</Button>
+    )
+  }
+}
+
+export default FuncButton
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/tabviews/zshare/actionList/funcbutton/index.scss
similarity index 100%
rename from src/tabviews/zshare/actionList/shareLink/index.scss
rename to src/tabviews/zshare/actionList/funcbutton/index.scss
diff --git a/src/tabviews/zshare/actionList/funczip/index.jsx b/src/tabviews/zshare/actionList/funczip/index.jsx
index e308d90..5181920 100644
--- a/src/tabviews/zshare/actionList/funczip/index.jsx
+++ b/src/tabviews/zshare/actionList/funczip/index.jsx
@@ -99,12 +99,15 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { BID, btn, selectedData, setting } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { BID, btn, selectedData, setting, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
+
+    let data = record || selectedData || []
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -113,13 +116,7 @@
         duration: 5
       })
       return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
-
-    let data = record || selectedData || []
-    
-    if (btn.Ot !== 'notRequired' && data.length === 0) {
+    } else if (btn.Ot !== 'notRequired' && data.length === 0) {
       notification.warning({
         top: 92,
         message: '璇烽�夋嫨琛岋紒',
@@ -409,42 +406,25 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
     
     return (
-      <>
-        <Button
-          type={type}
-          title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
-          loading={loading}
-          disabled={disabled}
-          style={btn.style}
-          icon={icon}
-          className={className}
-          onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
-        >{label}</Button>
-      </>
+      <Button
+        type="link"
+        title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
+        loading={loading}
+        disabled={disabled}
+        style={btn.style}
+        className={btn.hover || ''}
+        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
+      >{label}</Button>
     )
   }
 }
diff --git a/src/tabviews/zshare/actionList/index.jsx b/src/tabviews/zshare/actionList/index.jsx
index 3993d7e..8e213d8 100644
--- a/src/tabviews/zshare/actionList/index.jsx
+++ b/src/tabviews/zshare/actionList/index.jsx
@@ -19,7 +19,7 @@
 const FuncZip = asyncComponent(() => import('./funczip'))
 const EditLine = asyncComponent(() => import('./editLine'))
 const ExportPdf = asyncComponent(() => import('./exportPdf'))
-const ShareLink = asyncComponent(() => import('./shareLink'))
+const FuncButton = asyncComponent(() => import('./funcbutton'))
 
 class ActionList extends Component {
   static propTpyes = {
@@ -197,26 +197,26 @@
               btn={item}
             />
           )
-        } else if (item.funcType === 'shareLink') {
+        } else if (item.funcType === 'addline' || item.funcType === 'delline') {
           return (
-            <ShareLink
+            <EditLine
+            key={item.uuid}
+            disabled={false}
+            btn={item}
+            selectedData={selectedData}
+            />
+            )
+          }
+        } else {
+          return (
+            <FuncButton
               key={item.uuid}
               BID={BID}
               btn={item}
               selectedData={selectedData}
             />
           )
-        } else if (item.funcType === 'addline' || item.funcType === 'delline') {
-          return (
-            <EditLine
-              key={item.uuid}
-              disabled={false}
-              btn={item}
-              selectedData={selectedData}
-            />
-          )
         }
-      }
       return null
     })
   }
diff --git a/src/tabviews/zshare/actionList/index.scss b/src/tabviews/zshare/actionList/index.scss
index 23d8916..700f589 100644
--- a/src/tabviews/zshare/actionList/index.scss
+++ b/src/tabviews/zshare/actionList/index.scss
@@ -17,6 +17,19 @@
     padding: 0 15px;
   }
 
+  .ant-btn.mk-btn-hover-bg:not([disabled]):hover {
+    opacity: 1!important;
+    color: #ffffff!important;
+    border-color: var(--mk-sys-color)!important;
+    background-color: var(--mk-sys-color)!important;
+  }
+  .ant-btn.mk-btn-hover-border:not([disabled]):hover {
+    opacity: 1!important;
+    color: var(--mk-sys-color)!important;
+    border-color: var(--mk-sys-color)!important;
+    background-color: #ffffff!important;
+  }
+
   .loading-skeleton {
     background: -webkit-gradient(linear,left top,right top,color-stop(25%,#f5f5f5),color-stop(37%,#ffffff),color-stop(63%,#f5f5f5));
     background: linear-gradient(90deg,#f5f5f5 25%,#ffffff 37%,#f5f5f5 63%);
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 01d678e..5a78f3e 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -16,6 +16,7 @@
     btn: PropTypes.object,            // 鎸夐挳
     selectedData: PropTypes.any,      // 瀛愯〃涓�夋嫨鏁版嵁
     disabled: PropTypes.any,          // 琛屾寜閽鐢�
+    name: PropTypes.any
   }
 
   state = {
@@ -99,16 +100,13 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { btn, selectedData, BID } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { btn, selectedData, BID, LID } = this.props
     const { disabled } = this.state
 
     if (disabled) return
     if (triggerId && btn.uuid !== triggerId) return
-
-    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
 
     let data = record || selectedData || []
 
@@ -159,18 +157,75 @@
 
     if (btn.pageTemplate === 'billprint') {
       _name = '鍗曟嵁鎵撳嵃'
-      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') })))
-          window.open(url)
-        })
-      } else if (btn.Ot === 'requiredOnce') {
-        Id = data.map(item => item.$$uuid).filter(Boolean).join(',')
+      if (btn.preHandle === 'true' && btn.pre_func) {
+        MKEmitter.emit('queryModuleParam', btn.$menuId, (res) => {
+          let searches = {}
+          res.search && res.search.forEach(item => {
+            searches[item.key] = item.value
+          })
 
-        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+          if (btn.Ot === 'requiredOnce') {
+            Id = data.map(item => item.$$uuid).filter(Boolean).join(',')
+          }
+
+          if (btn.Ot === 'required') {
+            data.forEach(item => {
+              let _param = { id: item.$$uuid || '', tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+              try {
+                // eslint-disable-next-line
+                let func = new Function('btn', 'searches', 'data', 'param', 'systemType', btn.pre_func)
+                _param = func(btn, searches, [item], _param, window.GLOB.systemType)
+              } catch (e) {
+                console.warn(e)
+              }
+
+              if (!_param || _param.error) {
+                notification.warning({
+                  top: 92,
+                  message: _param ? _param.error : '鏈幏鍙栧埌鎵撳嵃鍙傛暟锛岃嚜瀹氫箟鑴氭湰閿欒锛�',
+                  duration: 5
+                })
+                return
+              }
+              
+              window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
+            })
+          } else {
+            let _param = { id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+            try {
+              // eslint-disable-next-line
+              let func = new Function('btn', 'searches', 'data', 'param', 'systemType', btn.pre_func)
+              _param = func(btn, searches, data, _param, window.GLOB.systemType)
+            } catch (e) {
+              console.warn(e)
+            }
+
+            if (!_param || _param.error) {
+              notification.warning({
+                top: 92,
+                message: _param ? _param.error : '鏈幏鍙栧埌鎵撳嵃鍙傛暟锛岃嚜瀹氫箟鑴氭湰閿欒锛�',
+                duration: 5
+              })
+              return
+            }
+
+            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') }))))
+        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') })))
+            window.open(url)
+          })
+        } else if (btn.Ot === 'requiredOnce') {
+          Id = data.map(item => item.$$uuid).filter(Boolean).join(',')
+  
+          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+        } else {
+          window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: Id, tempId: btn.printTemp, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+        }
       }
     } else if (btn.pageTemplate === 'billprintTemp') {
       let src = '#/menudesign/' + window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'billPrint', MenuId: Id, MenuNo: MenuNo, MenuName: name || '鎵撳嵃', Remark: Remark })))
@@ -212,10 +267,7 @@
       
       if (/#\/iframe\//.test(url)) {
         url = url.replace(/@loginuid@/ig, sessionStorage.getItem('LoginUID'))
-
-        if (btn.joint === 'true' && Id) {
-          url = url + '/' + Id
-        }
+        url = url + '/' + Id
 
         let menu = {
           MenuID: btn.uuid,
@@ -229,16 +281,26 @@
         return
       }
       
-      let con = '?'
-
-      if (/\?/ig.test(url)) {
-        con = '&'
-      }
-
       if (btn.joint === 'true') {
+        let con = '?'
+  
+        if (/\?/ig.test(url)) {
+          con = '&'
+        }
         url = url + `${con}id=${Id}&appkey=${window.GLOB.appkey}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
-      } else if (Id) {
-        url = url + `${con}id=${Id}`
+      } else if (/@/.test(url)) {
+        url = url.replace(/@id@/ig, Id)
+        url = url.replace(/@appkey@/ig, window.GLOB.appkey)
+        url = url.replace(/@userid@/ig, sessionStorage.getItem('UserID'))
+        url = url.replace(/@LoginUID@/ig, sessionStorage.getItem('LoginUID'))
+
+        if (btn.Ot === 'requiredSgl' && data[0]) {
+          Object.keys(data[0]).forEach(key => {
+            if (/^\$/.test(key)) return
+            let reg = new RegExp('@' + key + '@', 'ig')
+            url = url.replace(reg, data[0][key])
+          })
+        }
       }
 
       window.open(url)
@@ -250,44 +312,29 @@
   }
 
   render() {
-    const { btn } = this.props
+    const { btn, name } = this.props
     const { disabled, hidden } = this.state
 
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{name || btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <MkIcon type={btn.icon} />
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{name || btn.label}</span>
     }
 
     return (
       <Button
-        type={type}
+        type="link"
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         style={btn.style || null}
         disabled={disabled}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index f58f2fe..d4f7524 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -28,6 +28,7 @@
     columns: PropTypes.any,           // 瀛楁鍒�
     setting: PropTypes.any,           // 椤甸潰閫氱敤璁剧疆
     disabled: PropTypes.any,          // 琛屾寜閽鐢�
+    name: PropTypes.any
   }
 
   state = {
@@ -203,8 +204,8 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type, callback) => {
-    const { btn, selectedData } = this.props
+  actionTrigger = (triggerId, record, type, lid, callback) => {
+    const { btn, selectedData, LID } = this.props
     const { loading, disabled } = this.state
 
     if (type === 'preButton') {
@@ -218,7 +219,7 @@
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
-    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
     if (btn.OpenType === 'form' && btn.formType === 'count_line') return
 
     this.setState({autoMatic: type === 'autoMatic'})
@@ -755,6 +756,9 @@
         param.username = sessionStorage.getItem('User_Name') || ''
         param.fullname = sessionStorage.getItem('Full_Name') || ''
       }
+      if (btn.dataM === 'true') {
+        param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+      }
       
       let primaryId = ''
 
@@ -796,6 +800,9 @@
         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' : ''
         }
 
         let primaryId = setting.primaryKey ? cell[setting.primaryKey] || '' : ''
@@ -1086,7 +1093,7 @@
     let node = document.getElementById('button' + btnId)
 
     if (node) {
-      MKEmitter.emit('triggerBtnId', btnId, null, 'preButton', (res) => {
+      MKEmitter.emit('triggerBtnId', btnId, null, 'preButton', null, (res) => {
         if (!res) {
           this.setState({loading: false})
           resolve()
@@ -1631,11 +1638,12 @@
       })
 
       keys = keys.join(',')
+      vals = vals.join(',')
 
       lines.push({
         table: md5(tb + keys),
-        insert: `Insert into ${tbName} (${keys},[mk_level],[mk_id],[mk_bid])`,
-        select: `Select ${vals.join(',')},'${level}','${id}','${bid}'`
+        insert: `Insert into ${tbName} (${keys ? keys + ',' : ''}[mk_level],[mk_id],[mk_bid])`,
+        select: `Select ${keys ? vals + ',' : ''}'${level}','${id}','${bid}'`
       })
 
       subObjs.forEach(item => {
@@ -2344,9 +2352,9 @@
       tabId = btn.refreshTab[btn.refreshTab.length - 1]
     }
 
-    if (btn.formCache === 'clear') { // 娓呴櫎琛ㄥ崟缂撳瓨
-      window.GLOB.CacheMap = new Map()
-    }
+    // if (btn.formCache === 'clear') { // 娓呴櫎琛ㄥ崟缂撳瓨
+    //   window.GLOB.CacheMap = new Map()
+    // }
 
     if (tabId && btn.$MenuID === tabId) { // 鍒锋柊褰撳墠鑿滃崟鏃讹紝鍋滄鍏朵粬鎿嶄綔
       MKEmitter.emit('reloadMenuView', tabId, 'table')
@@ -2428,6 +2436,24 @@
     if (btn.execSuccess === 'popclose' && btn.$tabId) { // 鏍囩鍏抽棴鍒锋柊
       MKEmitter.emit('refreshPopButton', btn.$tabId)
     }
+
+    if (btn.verify && btn.verify.linkEnable === 'true') {
+      let url = ''
+      if (window.GLOB.systemType === 'production') {
+        url = btn.verify.linkProUrl
+        if (!url) {
+          notification.warning({
+            top: 92,
+            message: '灏氭湭娣诲姞姝e紡绯荤粺閾炬帴鍦板潃锛�',
+            duration: 5
+          })
+          return
+        }
+      } else {
+        url = btn.verify.linkUrl
+      }
+      window.open(url)
+    }
   }
 
   triggerNote = (res, ID) => {
@@ -2474,9 +2500,38 @@
 
     if (!id) return
 
-    setTimeout(() => {
-      window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: id, tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
-    }, 500)
+    if (btn.verify.preHandle === 'true' && btn.verify.pre_func && /#position-print/.test(btn.verify.pre_func)) {
+      MKEmitter.emit('queryModuleParam', btn.$menuId, (res) => {
+        let searches = {}
+        res.search && res.search.forEach(item => {
+          searches[item.key] = item.value
+        })
+        let _param = { id: id || '', tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM')}
+
+        try {
+          // eslint-disable-next-line
+          let func = new Function('btn', 'searches', 'param', 'systemType', btn.verify.pre_func)
+          _param = func(btn, searches, _param, window.GLOB.systemType)
+        } catch (e) {
+          console.warn(e)
+        }
+
+        if (!_param || _param.error) {
+          notification.warning({
+            top: 92,
+            message: _param ? _param.error : '鏈幏鍙栧埌鎵撳嵃鍙傛暟锛岃嚜瀹氫箟鑴氭湰閿欒锛�',
+            duration: 5
+          })
+          return
+        }
+        
+        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify(_param))))
+      })
+    } else {
+      setTimeout(() => {
+        window.open('#/billprint/' + window.btoa(window.encodeURIComponent(JSON.stringify({ id: id, tempId: btn.verify.printTempId, pageId: btn.$MenuID || '', dataM: sessionStorage.getItem('dataM') }))))
+      }, 200)
+    }
   }
 
   sendWxMessage = (verify, id) => {
@@ -3169,7 +3224,7 @@
   }
 
   modelconfirm = () => {
-    const { btn, BID } = this.props
+    const { BID } = this.props
     const { btnconfig, selines } = this.state
     let _this = this
 
@@ -3314,7 +3369,7 @@
       this.execSubmit(selines, () => {}, result)
     } else {
       confirm({
-        title: btn.tipTitle || '纭畾瑕佹墽琛屽悧?',
+        title: btnconfig.setting.tipTitle || '纭畾瑕佹墽琛屽悧?',
         onOk() {
           return new Promise(resolve => {
             _this.execSubmit(selines, resolve, result)
@@ -3494,7 +3549,7 @@
   }
 
   render() {
-    const { btn } = this.props
+    const { btn, name } = this.props
     const { loadingNumber, loadingTotal, loading, disabled, hidden, check, count } = this.state
 
     if (hidden) return null
@@ -3513,42 +3568,25 @@
     }
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{name || btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + (btn.class || 'unset')
+      label = !loading ? <MkIcon type={btn.icon} /> : null
+    } else if (btn.$toolbtn) {
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{loadingNumber && !loadingTotal ? `(${loadingNumber})` : ''}{btn.label}</span>
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + (btn.class || 'unset')
-    }
-
-    if (loadingNumber && btn.progress !== 'progressbar' && btn.$toolbtn && (!btn.show || btn.show === 'button')) {
-      label = (loadingNumber ? `(${loadingNumber})` : '') + btn.label
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{name || btn.label}</span>
     }
 
     let BTN = <Button
-      type={type}
-      icon={icon}
+      type="link"
       id={'button' + btn.uuid}
       title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
       loading={loading}
       disabled={disabled}
       style={btn.style}
-      className={className}
+      className={btn.hover || ''}
       onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
     >{label}</Button>
 
diff --git a/src/tabviews/zshare/actionList/popupbutton/index.jsx b/src/tabviews/zshare/actionList/popupbutton/index.jsx
index 7c34a66..dce034b 100644
--- a/src/tabviews/zshare/actionList/popupbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/popupbutton/index.jsx
@@ -20,6 +20,7 @@
     btn: PropTypes.object,            // 鎸夐挳
     setting: PropTypes.any,           // 椤甸潰閫氱敤璁剧疆
     disabled: PropTypes.any,          // 琛屾寜閽鐢�
+    name: PropTypes.any
   }
 
   state = {
@@ -140,12 +141,15 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { setting, BID, btn, selectedData } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { setting, BID, btn, selectedData, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
+
+    let data = record || selectedData || []
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -154,13 +158,7 @@
         duration: 5
       })
       return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
-
-    let data = record || selectedData || []
-
-    if (btn.Ot === 'requiredSgl' && data.length !== 1) {
+    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
       // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
       notification.warning({
         top: 92,
@@ -173,9 +171,9 @@
     let _data = null
     let primaryId = ''
 
-    if (btn.Ot === 'requiredSgl' && setting.primaryKey) {
+    if (btn.Ot === 'requiredSgl') {
       _data = data[0]
-      primaryId = _data.$$uuid || _data[setting.primaryKey] || ''
+      primaryId = _data.$$uuid || ''
     }
 
     this.setState({
@@ -303,46 +301,31 @@
   }
 
   render() {
-    const { btn } = this.props
+    const { btn, name } = this.props
     const { loading, disabled, hidden } = this.state
 
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{name || btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{name || btn.label}</span>
     }
 
     return (
       <>
         <Button
-          type={type}
+          type="link"
           id={'button' + btn.uuid}
           title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
-          loading={loading}
+          loading={loading && !name}
           disabled={disabled}
           style={btn.style}
-          icon={icon}
-          className={className}
+          className={btn.hover || ''}
           onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
         >{label}</Button>
         <span onClick={(e) => {e.stopPropagation()}} onDoubleClick={(e) => {e.stopPropagation()}}>{this.getPop()}</span>
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index 6627f32..8373813 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -130,12 +130,13 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { BID, btn, selectedData, setting } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { BID, btn, selectedData, setting, LID } = this.props
     const { loading, disabled } = this.state
 
     if (loading || disabled) return
     if (triggerId && btn.uuid !== triggerId) return
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
 
     if (setting.supModule && !BID) {
       notification.warning({
@@ -143,8 +144,6 @@
         message: '闇�瑕佷笂绾т富閿�硷紒',
         duration: 5
       })
-      return
-    } else if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
       return
     }
 
@@ -915,6 +914,9 @@
               _param.username = sessionStorage.getItem('User_Name') || ''
               _param.fullname = sessionStorage.getItem('Full_Name') || ''
             }
+            if (btn.dataM === 'true') {
+              _param.dataM = sessionStorage.getItem('dataM') === 'true' ? 'Y' : ''
+            }
   
             return _param
           })
@@ -1007,7 +1009,11 @@
     }
 
     let isDataM = sessionStorage.getItem('dataM') === 'true'
+    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript + _tailScript)
     let regoptions = [
+      { reg: /@orderBy@/ig, value: btn.verify.setting.order },
+      { reg: /@pageSize@/ig, value: '9999' },
+      { reg: /@pageIndex@/ig, value: '1'},
       { reg: /@ID@/ig, value: `'${ID}'`},
       { reg: /@BID@/ig, value: `'${BID || ''}'`},
       { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
@@ -1125,7 +1131,11 @@
     let LText = ''
 
     if (_dataresource) {
-      LText = `/*system_query*/select ${arrFields} from (select ${arrFields} ,ROW_NUMBER() over(order by ${btn.verify.setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
+      if (custompage) {
+        LText = `/*system_query*/select ${arrFields} from ${_dataresource} `
+      } else {
+        LText = `/*system_query*/select ${arrFields} from (select ${arrFields} ,ROW_NUMBER() over(order by ${btn.verify.setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
+      }
     }
 
     if (_customScript) {
@@ -2357,39 +2367,24 @@
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = !loading ? <MkIcon type={btn.icon} /> : null
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
     }
 
     return <>
       <Button
-        type={type}
+        type="link"
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         loading={loading}
         disabled={disabled}
         style={btn.style || null}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
       <span onClick={(e) => {e.stopPropagation()}}>{this.getModels()}</span>
diff --git a/src/tabviews/zshare/actionList/shareLink/index.jsx b/src/tabviews/zshare/actionList/shareLink/index.jsx
deleted file mode 100644
index e4bd407..0000000
--- a/src/tabviews/zshare/actionList/shareLink/index.jsx
+++ /dev/null
@@ -1,193 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Button, notification, message, Modal } from 'antd'
-import md5 from 'md5'
-
-import Api from '@/api'
-import MKEmitter from '@/utils/events.js'
-import MkIcon from '@/components/mk-icon'
-
-// import './index.scss'
-
-class ShareLink extends Component {
-  static propTpyes = {
-    BID: PropTypes.string,
-    btn: PropTypes.object,
-    selectedData: PropTypes.any
-  }
-
-  state = {
-    loading: false
-  }
-
-  componentDidMount () {
-    MKEmitter.addListener('triggerBtnId', this.actionTrigger)
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  componentWillUnmount () {
-    this.setState = () => {
-      return
-    }
-    MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
-  }
-
-  /**
-   * @description 瑙﹀彂鎸夐挳鎿嶄綔
-   */
-  actionTrigger = (triggerId) => {
-    const { btn, BID, selectedData } = this.props
-    const { loading } = this.state
-
-    if (loading) return
-    if (triggerId && btn.uuid !== triggerId) return
-
-    if (window.GLOB.systemType === 'production' && !btn.shareProUrl) {
-      notification.warning({
-        top: 92,
-        message: '灏氭湭璁剧疆姝e紡绯荤粺閾炬帴鍦板潃锛�',
-        duration: 5
-      })
-      return
-    }
-
-    let bid = BID || ''
-    let id = ''
-    if (selectedData && selectedData[0]) {
-      id = selectedData[0].$$uuid || ''
-    }
-
-    let url = btn.shareUrl
-    if (window.GLOB.systemType === 'production') {
-      url = btn.shareProUrl
-    }
-
-    url = url.replace(/@BID@/ig, bid).replace(/@ID@/ig, id)
-
-    if (btn.shortUrl === 'true') {
-      this.setState({
-        loading: true
-      }, () => {
-        this.getShortUrl(url)
-      })
-    } else {
-      this.copyUrl(url)
-    }
-  }
-
-  getShortUrl = (url) => {
-    let _rduri = window.atob('aHR0cHM6Ly9lcGMubWs5aC5$mkjbi93ZWJhcGkvZG9zdGFycw=='.replace(/\$mk/ig, ''))
-    let _id = window.atob('YmgwYmFwYWJ0ZDQ1ZXBz$mkZ3JhNzlzZWdiY2g2YzFpYms='.replace(/\$mk/ig, ''))
-
-    let param = {
-      func: 's_url_db_adduptdel',
-      appkey: window.GLOB.appkey,
-      userid: _id,
-      LoginUID: _id,
-      type: 'add_only',
-      validity: 15,
-      linkurl: url,
-      nonc: '' + new Date().getTime(),
-      id: md5(url + window.GLOB.appkey)
-    }
-
-    let keys = Object.keys(param).sort()
-    let values = ''
-    keys.forEach(key => {
-      values += key + param[key]
-    })
-    param.sign = md5(values)
-    param.t = new Date().getTime()
-
-    Api.directRequest({
-      url: _rduri + '/s_url_db_adduptdel',
-      method: 'post',
-      data: JSON.stringify(param)
-    }).then(res => {
-      this.setState({
-        loading: false
-      })
-
-      if (res.status && res.id) {
-        this.copyUrl('https://mk9h.cn/m.asp?m=' + res.id)
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message || '閾炬帴鐢熸垚澶辫触锛�',
-          duration: 5
-        })
-      }
-    }, () => {
-      this.setState({
-        loading: false
-      })
-    })
-  }
-
-  copyUrl = (url) => {
-    const { btn } = this.props
-
-    let oInput = document.createElement('input')
-    oInput.value = url
-    document.body.appendChild(oInput)
-    oInput.select()
-    document.execCommand('Copy')
-    document.body.removeChild(oInput)
-
-    if (btn.shareTip) {
-      Modal.success({
-        title: btn.shareTip
-      })
-    } else {
-      message.success('宸插鍒跺埌鍓垏鏉裤��')
-    }
-  }
-
-  render() {
-    const { btn } = this.props
-    const { loading } = this.state
-
-    let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
-    let style = {...btn.style}
-
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
-    } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
-    } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
-    }
-    
-    return (
-      <Button
-        type={type}
-        title={btn.show === 'icon' ? btn.label : ''}
-        style={style}
-        loading={loading}
-        icon={icon}
-        className={className}
-        onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
-      >{label}</Button>
-    )
-  }
-}
-
-export default ShareLink
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx
index af1a136..d96f206 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -1,11 +1,12 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Button, notification } from 'antd'
+import { Button, notification, Dropdown } from 'antd'
 
 import MKEmitter from '@/utils/events.js'
 import MkIcon from '@/components/mk-icon'
-// import './index.scss'
+
+import './index.scss'
 
 class TabButton extends Component {
   static propTpyes = {
@@ -15,6 +16,7 @@
     btn: PropTypes.object,            // 鎸夐挳
     selectedData: PropTypes.any,      // 瀛愯〃涓�夋嫨鏁版嵁
     disabled: PropTypes.any,          // 琛屾寜閽鐢�
+    name: PropTypes.any
   }
 
   state = {
@@ -98,16 +100,13 @@
   /**
    * @description 瑙﹀彂鎸夐挳鎿嶄綔
    */
-  actionTrigger = (triggerId, record, type) => {
-    const { btn, selectedData, BID } = this.props
+  actionTrigger = (triggerId, record, type, lid) => {
+    const { btn, selectedData, BID, LID } = this.props
     const { disabled } = this.state
 
-    if (disabled) return
+    if (disabled || btn.multiMenus) return
     if (triggerId && btn.uuid !== triggerId) return
-
-    if (type === 'linkbtn' && !btn.$toolbtn && !is(fromJS(selectedData || []), fromJS(record))) {
-      return
-    }
+    if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
     
     let data = record || selectedData || []
 
@@ -137,8 +136,22 @@
       let ids = data.map(d => (d.$$uuid || ''))
       ids = ids.filter(Boolean)
       primaryId = ids.join(',')
-    } else if (btn.Ot === 'notRequired' && BID) {
-      primaryId = BID
+    } else if (btn.Ot === 'notRequired') {
+      if (btn.sysId === 'js') {
+        primaryId = (() => {
+          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
+        })()
+        primaryId = primaryId + (btn.sign || '')
+      } else if (btn.sysId !== 'empty') {
+        primaryId = BID || ''
+      }
     }
 
     let newtab = {}
@@ -180,6 +193,14 @@
         return
       }
 
+      if (btn.Ot === 'requiredSgl' || btn.Ot === 'requiredOnce') {
+        Object.keys(data[0]).forEach(key => {
+          if (/^\$/.test(key)) return
+          if (key === 'children') return
+          menu.param[key] = data[0][key]
+        })
+      }
+
       newtab = menu
     }
 
@@ -196,45 +217,132 @@
     }
   }
 
+  triggerMenu = (tab) => {
+    const { btn, selectedData, BID } = this.props
+
+    let data = selectedData || []
+
+    if (btn.Ot !== 'notRequired' && data.length === 0) {
+      // 闇�瑕侀�夋嫨琛屾椂锛屾牎楠屾暟鎹�
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨琛岋紒',
+        duration: 5
+      })
+      return false
+    } else if (btn.Ot === 'requiredSgl' && data.length !== 1) {
+      // 闇�瑕侀�夋嫨鍗曡鏃讹紝鏍¢獙鏁版嵁
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨鍗曡鏁版嵁锛�',
+        duration: 5
+      })
+      return
+    }
+
+    let primaryId = ''
+
+    if (btn.Ot === 'requiredSgl') {
+      primaryId = data[0].$$uuid || ''
+    } else if (btn.Ot === 'requiredOnce') {
+      let ids = data.map(d => (d.$$uuid || ''))
+      ids = ids.filter(Boolean)
+      primaryId = ids.join(',')
+    } else if (btn.Ot === 'notRequired') {
+      if (btn.sysId === 'js') {
+        primaryId = (() => {
+          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
+        })()
+        primaryId = primaryId + (tab.sign || '')
+      } else if (btn.sysId !== 'empty') {
+        primaryId = BID || ''
+      }
+    }
+
+    let menuId = tab.menuId.slice(-1)[0]
+    let menu = null
+
+    if (window.GLOB.mkThdMenus.has(menuId)) {
+      menu = {...window.GLOB.mkThdMenus.get(menuId), param: { $BID: primaryId }}
+    } else if (tab.MenuID) {
+      menu = {
+        MenuID: tab.MenuID,
+        MenuName: tab.MenuName,
+        type: tab.tabType,
+        param: { $BID: primaryId }
+      }
+    }
+
+    if (!menu) {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+        duration: 5
+      })
+      return
+    }
+
+
+    if (btn.openTab === 'view') {
+      window.open('#/view/' + menu.MenuID + '/' + primaryId)
+    } else {
+      MKEmitter.emit('modifyTabs', menu, true)
+  
+      MKEmitter.emit('openNewTab')
+    }
+
+    if (window.GLOB.systemType === 'production') {
+      MKEmitter.emit('queryTrigger', {menuId: btn.uuid, name: '鏍囩椤�'})
+    }
+  }
+
   render() {
-    const { btn } = this.props
+    const { btn, name } = this.props
     const { disabled, hidden } = this.state
 
     if (hidden) return null
 
     let label = ''
-    let icon = ''
-    let type = 'link'
-    let className = ''
 
-    if (btn.show === 'button') {
-      label = btn.label
-      icon = btn.icon || ''
-    } else if (btn.show === 'link') {
-      label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon}/> : ''}</span>
-      icon = ''
+    if (btn.show === 'link') {
+      label = <span>{name || btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
     } else if (btn.show === 'icon') {
-      icon = btn.icon || ''
-    } else if (!btn.$toolbtn) {
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <MkIcon type={btn.icon} />
     } else {
-      type = ''
-      icon = btn.icon || ''
-      label = btn.label
-      className = 'mk-btn mk-' + btn.class
+      label = <span>{btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{name || btn.label}</span>
+    }
+
+    if (btn.multiMenus && !disabled) {
+      return (<Dropdown
+        overlay={<div className="mk-tab-dropdown-wrap">{
+          btn.multiMenus.map(tab => <div key={tab.uuid} onClick={() => this.triggerMenu(tab)}>{tab.name}</div>)
+        }</div>}
+        trigger={['hover']}
+      >
+        <Button
+          type="link"
+          title={btn.show === 'icon' ? btn.label : ''}
+          style={btn.style || null}
+          className={btn.hover || ''}
+        >{label}</Button>
+      </Dropdown>)
     }
 
     return (
       <Button
-        type={type}
+        type="link"
         id={'button' + btn.uuid}
         title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
         style={btn.style || null}
         disabled={disabled}
-        icon={icon}
-        className={className}
+        className={btn.hover || ''}
         onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
       >{label}</Button>
     )
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.scss b/src/tabviews/zshare/actionList/tabbutton/index.scss
index 8b13789..6401b82 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.scss
+++ b/src/tabviews/zshare/actionList/tabbutton/index.scss
@@ -1 +1,19 @@
+.mk-tab-dropdown-wrap {
+  box-shadow: 0 0 2px #bcbcbc;
+  background: #ffffff;
+  min-width: 85px;
+  border-radius: 2px;
 
+  div {
+    height: 32px;
+    line-height: 32px;
+    padding: 0 15px;
+    color: rgba(0, 0, 0, 0.65);
+    background: #ffffff;
+    cursor: pointer;
+  }
+  div:hover {
+    background-color: var(--mk-sys-color);
+    color: #ffffff;
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/automatic/index.jsx b/src/tabviews/zshare/automatic/index.jsx
index 8d3f243..d165c28 100644
--- a/src/tabviews/zshare/automatic/index.jsx
+++ b/src/tabviews/zshare/automatic/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Button, message } from 'antd'
+import { Button, message, Tooltip } from 'antd'
 
 import MKEmitter from '@/utils/events.js'
 // import './index.scss'
@@ -224,7 +224,9 @@
 
     return (
       <div className="tool-wrap">
-        <Button icon={running ? 'pause' : 'forward'} shape="circle" onClick={this.trigger}/>
+        <Tooltip placement="left" title="鏃犱汉鍊煎畧">
+          <Button icon={running ? 'pause' : 'forward'} shape="circle" onClick={this.trigger}/>
+        </Tooltip>
       </div>
     )
   }
diff --git a/src/tabviews/zshare/flowFloat/index.jsx b/src/tabviews/zshare/flowFloat/index.jsx
index 5aab582..631b307 100644
--- a/src/tabviews/zshare/flowFloat/index.jsx
+++ b/src/tabviews/zshare/flowFloat/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Button, Modal, notification, Spin, Empty } from 'antd'
+import { Button, Modal, notification, Spin, Empty, Tooltip } from 'antd'
 import { BranchesOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
@@ -191,7 +191,9 @@
 
     return (
       <div className="tool-wrap">
-        <Button shape="circle" onClick={this.trigger}><BranchesOutlined /></Button>
+        <Tooltip placement="left" title="宸ヤ綔娴�">
+          <Button shape="circle" onClick={this.trigger}><BranchesOutlined /></Button>
+        </Tooltip>
         <Modal
           wrapClassName="flow-setting-modal"
           title="宸ヤ綔娴�"
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index c987f75..483d428 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -148,6 +148,7 @@
       item.readin = item.readin !== 'false' && item.readin !== 'top'
       item.readonly = check || item.readonly === 'true'
       item.writein = item.writein !== 'false'
+      item.defHidden = item.hidden === 'true'
       item.hidden = item.hidden === 'true'
       item.fieldlength = item.fieldlength || 50
 
@@ -403,11 +404,13 @@
           message: item.label + '涓嶅彲涓虹┖!'
         }]
 
-        if (typeof(item.min) === 'number' || typeof(item.max) === 'number') {
+        if (typeof(item.min) === 'number' || typeof(item.max) === 'number' || item.notZero === 'true') {
           item.rules.push({
             validator: (rule, value, callback) => {
               if (isNaN(value)) {
                 callback()
+              } else if (item.notZero === 'true' && value === 0) {
+                callback(item.label + '涓嶅彲涓�0')
               } else if (typeof(item.min) === 'number' && value < item.min) {
                 if (item.min < 1e-6) {
                   if (item.min === 1e-6) {
@@ -508,7 +511,7 @@
 
         let _hidden = false
 
-        if (supItem.hidden) {
+        if (supItem.hidden && !supItem.defHidden) {
           _hidden = true
         } else {
           let box = [...item.values]
@@ -627,7 +630,11 @@
         item.supInitVal = ''
 
         if (fieldMap.has(item.linkField)) {
-          item.supInitVal = fieldMap.get(item.linkField).initval || ''
+          let supitem = fieldMap.get(item.linkField)
+          item.supInitVal = supitem.initval || ''
+          if (supitem.$first) {
+            item.$resetSup = true
+          }
         } else if (data.hasOwnProperty(item.linkField.toLowerCase())) {
           item.supInitVal = data[item.linkField.toLowerCase()]
         }
@@ -1097,7 +1104,11 @@
 
         // if (item.type === 'link') {
         if (item.linkField) {
-          item.options = item.oriOptions.filter(option => option.ParentID === item.supInitVal || option.value === '')
+          let supInitVal = item.supInitVal
+          if (item.$resetSup) {
+            supInitVal = this.record[item.linkField]
+          }
+          item.options = item.oriOptions.filter(option => option.ParentID === supInitVal || option.value === '')
         // } else if (['select', 'radio', 'checkbox', 'checkcard', 'multiselect'].includes(item.type)) {
         } else {
           item.options = item.oriOptions
@@ -1239,11 +1250,17 @@
       if (item.hidden) return
 
       if (item.type === 'split') {
-        fields.push(
-          <Col span={24} key={index}>
-            <p className="mk-form-split-line" style={item.style}>{item.label}</p>
-          </Col>
-        )
+        if (item.opacity === 'false') {
+          fields.push(
+            <div key={index}></div>
+          )
+        } else {
+          fields.push(
+            <Col span={24} key={index}>
+              <p className="mk-form-split-line" style={item.style}>{item.label}</p>
+            </Col>
+          )
+        }
       } else if (item.type === 'hint') {
         fields.push(
           <Col span={item.span || 24} key={index}>
@@ -1291,7 +1308,7 @@
         } else if (item.type === 'radio') {
           content = (<MKRadio config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
         } else if (item.type === 'date' || item.type === 'datemonth') {
-          content = (<MKDatePicker config={item} onChange={(val) => this.recordChange({[item.field]: val})} />)
+          content = (<MKDatePicker config={item} onChange={(val) => this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit}/>)
         } else if (item.type === 'fileupload') {
           className = item.readonly ? 'readonly' : ''
           className += item.fileType === 'picture-card' ? ' file-upload' : ''
diff --git a/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
index 0fe72ab..48ababe 100644
--- a/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkDatePicker/index.jsx
@@ -3,6 +3,8 @@
 import { DatePicker } from 'antd'
 import moment from 'moment'
 
+import MKEmitter from '@/utils/events.js'
+
 const { MonthPicker } = DatePicker
 
 /**
@@ -68,6 +70,17 @@
     }
 
     this.props.onChange(_val)
+
+    if (!config.enter || config.enter === 'false') return
+
+    setTimeout(() => {
+      if (config.enter === 'tab') {
+        MKEmitter.emit('mkFC', 'focus', config.tabUuid)
+      } else if (config.enter === 'sub') {
+        config.tabUuid && MKEmitter.emit('mkFC', 'focus', config.tabUuid)
+        this.props.onSubmit(config.tabUuid)
+      }
+    }, 50)
   }
 
   disabledDate = (current) => {
diff --git a/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
index 9e80af9..aa4d070 100644
--- a/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkNumberInput/index.jsx
@@ -78,8 +78,14 @@
   render() {
     const { config } = this.props
     const { value, precision } = this.state
-
-    if (precision === null) {
+    
+    if (config.format === 'thdSeparator') {
+      if (precision === null) {
+        return (<InputNumber id={config.uuid} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} value={value} disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleSubmit}/>)
+      } else {
+        return (<InputNumber id={config.uuid} formatter={value => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} parser={value => value.replace(/,*/g, '')} value={value} precision={precision} disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleSubmit} />)
+      }
+    } else if (precision === null) {
       return (<InputNumber id={config.uuid} value={value} disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleSubmit}/>)
     } else {
       return (<InputNumber id={config.uuid} value={value} precision={precision} disabled={config.readonly} onChange={this.handleChange} onPressEnter={this.handleSubmit} />)
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 44d6ab9..8439a3a 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -342,20 +342,22 @@
   // 瀛楁閫忚
   triggerLink = (e, item, record) => {
     e.stopPropagation()
-
-    let __param = {
-      $searchkey: item.field,
-      $searchval: record[item.field] || '',
-      $BID: record.$$uuid
-    }
-
-    if (item.linkfields && item.linkfields.length > 0) {
-      item.linkfields.forEach(field => {
-        __param[field] = record[field] || ''
-      })
-    }
-
+    
     if (item.linkThdMenu) {
+      let __param = {
+        $BID: record.$$uuid
+      }
+  
+      if (item.field) {
+        __param.$searchkey = item.field.toLowerCase()
+        __param.$searchval = record[item.field] || ''
+      }
+
+      Object.keys(record).forEach(key => {
+        if (/^\$/.test(key)) return
+        __param[key] = record[key]
+      })
+
       let tabmenu = item.linkThdMenu
       tabmenu.param = __param
 
@@ -738,6 +740,7 @@
         </div>
       )
     } else if (item.type === 'action') {
+      let lid = (record.$$uuid || '') + (record.$Index || '')
       return (
         <div className="action-col">
           {item.operations.map(btn => {
@@ -747,6 +750,7 @@
                   key={btn.uuid}
                   btn={btn}
                   BID={record.$$BID}
+                  LID={lid}
                   disabled={record.$disabled}
                   selectedData={[record]}
                   BData={this.props.BData}
@@ -760,6 +764,7 @@
                   key={btn.uuid}
                   btn={btn}
                   BID={record.$$BID}
+                  LID={lid}
                   disabled={record.$disabled}
                   selectedData={[record]}
                   BData={this.props.BData}
@@ -774,6 +779,7 @@
                   disabled={record.$disabled}
                   selectedData={[record]}
                   BID={record.$$BID}
+                  LID={lid}
                   BData={this.props.BData}
                   MenuID={this.props.MenuID}
                 />
@@ -784,6 +790,7 @@
                   key={btn.uuid}
                   btn={btn}
                   BID={record.$$BID}
+                  LID={lid}
                   disabled={record.$disabled}
                   selectedData={[record]}
                   BData={this.props.BData}
@@ -1209,7 +1216,7 @@
     if (!setting.doubleClick) return
     if (record.$disabled) return
 
-    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn')
+    MKEmitter.emit('triggerBtnId', setting.doubleClick, [record], 'linkbtn', (record.$$uuid || '') + (record.$Index || ''))
   }
 
   render() {
diff --git a/src/tabviews/zshare/normalTable/index.scss b/src/tabviews/zshare/normalTable/index.scss
index 75c4770..c65a3ae 100644
--- a/src/tabviews/zshare/normalTable/index.scss
+++ b/src/tabviews/zshare/normalTable/index.scss
@@ -10,11 +10,8 @@
     position: absolute;
     bottom: 40px;
   }
-  >.ant-table-wrapper {
-    position: relative;
-    z-index: 1;
-  }
   .ant-table-wrapper {
+    position: relative;
     color: rgba(0, 0, 0, 0.65);
     font-size: 14px;
     .ant-table {
diff --git a/src/tabviews/zshare/settingcomponent/index.jsx b/src/tabviews/zshare/settingcomponent/index.jsx
index f2488e9..77e2230 100644
--- a/src/tabviews/zshare/settingcomponent/index.jsx
+++ b/src/tabviews/zshare/settingcomponent/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Button, Modal, notification, Spin, Empty } from 'antd'
+import { Button, Modal, notification, Spin, Empty, Tooltip } from 'antd'
 
 import Api from '@/api'
 import MKEmitter from '@/utils/events.js'
@@ -522,10 +522,12 @@
 
     return (
       <div className="tool-wrap">
-        <Button icon="setting" shape="circle" onClick={this.trigger}/>
+        <Tooltip placement="left" title="鑷畾涔夎缃�">
+          <Button icon="setting" shape="circle" onClick={this.trigger}/>
+        </Tooltip>
         <Modal
           wrapClassName="custom-setting-modal"
-          title={'鑷畾涔夎缃�'}
+          title="鑷畾涔夎缃�"
           maskClosable={false}
           width={950}
           visible={visible}
diff --git a/src/tabviews/zshare/tablenodes/index.jsx b/src/tabviews/zshare/tablenodes/index.jsx
index 49f6f32..4a258bc 100644
--- a/src/tabviews/zshare/tablenodes/index.jsx
+++ b/src/tabviews/zshare/tablenodes/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Modal, Button, notification, Spin, Input, Typography, message } from 'antd'
+import { Modal, Button, notification, Spin, Input, Typography, message, Tooltip } from 'antd'
 
 import Api from '@/api'
 import G6 from "@antv/g6"
@@ -477,7 +477,9 @@
 
     return (
       <div className="tool-wrap">
-        <Button icon="fork" shape="circle" onClick={this.trigger}/>
+        <Tooltip placement="left" title="琛ㄥ叧绯诲浘">
+          <Button icon="fork" shape="circle" onClick={this.trigger}/>
+        </Tooltip>
         <Modal
           title=""
           wrapClassName="view-table-modal"
diff --git a/src/tabviews/zshare/topSearch/advanceform/index.scss b/src/tabviews/zshare/topSearch/advanceform/index.scss
index fa9af70..2312e65 100644
--- a/src/tabviews/zshare/topSearch/advanceform/index.scss
+++ b/src/tabviews/zshare/topSearch/advanceform/index.scss
@@ -7,6 +7,10 @@
     float: none;
     vertical-align: top;
   }
+  .ant-checkbox-wrapper {
+    color: rgba(0, 0, 0, 0.85);
+    white-space: nowrap;
+  }
   .ant-form-item {
     display: flex;
     margin-bottom: 0px;
@@ -32,6 +36,9 @@
   .ant-select-dropdown {
     z-index: 10 !important;
   }
+  .ant-radio-group {
+    white-space: nowrap;
+  }
   .ant-calendar-picker-container {
     z-index: 10 !important;
   }
diff --git a/src/tabviews/zshare/topSearch/index.jsx b/src/tabviews/zshare/topSearch/index.jsx
index 4e6d329..0e1c29d 100644
--- a/src/tabviews/zshare/topSearch/index.jsx
+++ b/src/tabviews/zshare/topSearch/index.jsx
@@ -42,7 +42,7 @@
   sign = ''
 
   UNSAFE_componentWillMount () {
-    const { config, BID } = this.props
+    const { config } = this.props
 
     let _searchlist = []
     let fieldMap = new Map()
@@ -54,6 +54,7 @@
     let record = {}
     let forbid = false // header涓笉璁剧疆楂樼骇鎼滅储
     let _setting = {showAdv: false, show: false, style: null}
+    let BID = this.props.BID
     
     if (config.wrap) {
       _setting.show = config.wrap.show !== 'false'
@@ -66,6 +67,15 @@
       _setting.wrapperCol = {style: {width: (100 - _setting.labelwidth) + '%'}}
       _setting.borderRadius = config.wrap.borderRadius
       _setting.resetContrl = config.wrap.resetContrl || 'init'
+
+      if (config.wrap.searchBtn === 'show') {
+        _setting.showBtn = true
+      }
+
+      if (config.wrap.supModule) {
+        let BData = window.GLOB.CacheData.get(config.wrap.supModule)
+        BID = BData ? (BData.$BID || '') : ''
+      }
     }
     
     if (config.type === 'search') {
@@ -178,20 +188,21 @@
         // 鏁版嵁婧愭煡璇㈣鍙�
         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`
 
           let exec = true
           if (item.checkBid) {
-            item.sql = _option.sql
+            item.sql = _declare + _option.sql
             item.arr_field = _option.field
 
             exec = !!BID
           }
 
           if (exec) {
-            _option.sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
+            let _sql = _option.sql.replace(/@BID@/ig, `'${BID || ''}'`)
   
             if (window.GLOB.debugger === true) {
-              console.info(_option.sql)
+              console.info(_declare + _sql)
             }
   
             // 娴嬭瘯绯荤粺鍗曚釜璇锋眰
@@ -199,13 +210,20 @@
               deForms.push({
                 ...item,
                 arr_field: _option.field,
-                data_sql: Utils.formatOptions(_option.sql, window.GLOB.execType)
+                data_sql: Utils.formatOptions(_declare + _sql, window.GLOB.execType)
               })
             } else { // 鍚堝苟璇锋眰锛屽尯鍒嗘湰鍦板強绯荤粺
+              _sql = _sql.replace(/%/ig, ' mpercent ')
               if (item.database === 'sso') {
-                mainItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
+                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 {
-                localItems.push(`select '${item.field}' as obj_name,'${_option.field}' as arr_field,'${window.btoa(window.encodeURIComponent(_option.sql.replace(/%/ig, ' mpercent ')))}' as LText`)
+                if (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`)
               }
             }
           }
@@ -278,19 +296,42 @@
       searchlist: _list
     }, () => {
       if (!window.GLOB.mkHS && window.GLOB.sysType === 'local' && window.GLOB.systemType !== 'production') {
-        this.improveSimpleSearch(deForms, false)
+        this.improveSimpleSearch(deForms, false, null, BID)
       } else if (mainItems.length > 0 || localItems.length > 0) {
-        this.improveSearch(mainItems, localItems)
+        this.improveSearch(mainItems, localItems, BID)
       }
     })
+  }
+
+  componentDidMount () {
+    const { config } = this.props
+
+    if (config.type === 'search' && config.wrap.supModule) {
+      MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+    }
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
   }
 
   UNSAFE_componentWillReceiveProps(nextProps) {
     const { config, BID } = this.props
 
-    if (config.checkBid && nextProps.BID !== BID) {
+    if (config.checkBid && config.type !== 'search' && nextProps.BID !== BID) {
       this.resetOptions(nextProps.BID)
     }
+  }
+
+  resetParentParam = (MenuID, id) => {
+    const { config } = this.props
+
+    if (config.wrap.supModule !== MenuID) return
+
+    this.resetOptions(id)
   }
 
   resetOptions = (BID) => {
@@ -346,7 +387,7 @@
     })
 
     if (deForms.length > 0) {
-      this.improveSimpleSearch(deForms, true, searchlist)
+      this.improveSimpleSearch(deForms, true, searchlist, BID)
     } else {
       this.setState({
         searchlist: searchlist
@@ -391,8 +432,7 @@
   }
 
   // 鏌ヨ涓嬫媺鑿滃崟
-  improveSearch = (mainItems, localItems) => {
-    const { BID } = this.props
+  improveSearch = (mainItems, localItems, BID) => {
     let deffers = []
 
     // 鏈湴璇锋眰
@@ -495,7 +535,7 @@
   }
 
   // 娴嬭瘯绯荤粺鍗曚釜璇锋眰涓嬫媺閫夐」
-  improveSimpleSearch = (deForms, trigger, searchlist) => {
+  improveSimpleSearch = (deForms, trigger, searchlist, BID) => {
     if (deForms.length === 0) return
 
     let deffers = deForms.map((item, index) => {
@@ -506,8 +546,8 @@
         arr_field: item.arr_field
       }
 
-      if (this.props.BID) {
-        param.BID = this.props.BID
+      if (BID) {
+        param.BID = BID
       }
 
       if (window.GLOB.execType === 'x') {
@@ -569,11 +609,11 @@
           }
 
           if (item.linkField) {
-            _item.ParentID = cell[item.linkField]
+            _item.ParentID = cell[item.linkField] + ''
           }
 
           if (item.type !== 'checkcard') {
-            _item.Value = cell[item.valueField]
+            _item.Value = cell[item.valueField] + ''
             _item.Text = cell[item.valueText] + ''
             
             if (map.has(_item.ParentID + _item.Value)) return
@@ -588,7 +628,7 @@
             
             map.set(_item.ParentID + _item.Value, 0)
           } else {
-            _item.$value = cell[item.cardValField]
+            _item.$value = cell[item.cardValField] + ''
             _item = {..._item, ...cell}
 
             if (item.urlField) {
@@ -761,6 +801,16 @@
           </Form.Item>
         </Col>
       )
+    } else if (setting.showBtn) {
+      fields.push(
+        <Col className="mk-search-col search-button" key="actions">
+          <Form.Item>
+            <Button type="primary" onClick={this.handleSubmit}>
+              鎼滅储
+            </Button>
+          </Form.Item>
+        </Col>
+      )
     }
     
     return fields
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 9d96cca..bf4590a 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -5,9 +5,11 @@
     display: inline-block;
     float: none;
     vertical-align: top;
+    text-align: left;
   }
   .ant-checkbox-wrapper {
     color: rgba(0, 0, 0, 0.85);
+    white-space: nowrap;
   }
   .ant-form-item {
     display: flex;
@@ -34,6 +36,9 @@
   .ant-select-dropdown {
     z-index: 10 !important;
   }
+  .ant-radio-group {
+    white-space: nowrap;
+  }
   .ant-calendar-picker-container {
     z-index: 10 !important;
   }
@@ -50,7 +55,7 @@
   }
   .search-button {
     min-height: 55px;
-    .ant-btn-link, .ant-btn-link:hover, .ant-btn-link:active{
+    .ant-btn-link, .ant-btn-link:hover, .ant-btn-link:active {
       border-color: transparent;
       span {
         position: relative;
diff --git a/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
index fc67c7d..3ec9b43 100644
--- a/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
+++ b/src/tabviews/zshare/topSearch/mkDatePicker/index.jsx
@@ -54,10 +54,21 @@
     const { config } = this.props
 
     if (config.checkShift && nextProps.config.initval && nextProps.config.initval !== config.initval) {
-      let val = nextProps.config.initval.split(',')
+      let value = nextProps.config.initval || null
+
+      if (this.state.mode === 'daterange') {
+        if (value) {
+          let val = value.split(',')
+          value = [moment(val[0], this.state.format), moment(val[1], this.state.format)]
+        } else {
+          value = [null, null]
+        }
+      } else if (value) {
+        value = moment(value, this.state.format)
+      }
 
       this.setState({
-        value: [moment(val[0], config.format), moment(val[1], config.format)]
+        value: value
       })
 
       this.props.onChange(nextProps.config.initval, true)
diff --git a/src/templates/comtableconfig/updatetable/index.jsx b/src/templates/comtableconfig/updatetable/index.jsx
index 97d5062..ed03667 100644
--- a/src/templates/comtableconfig/updatetable/index.jsx
+++ b/src/templates/comtableconfig/updatetable/index.jsx
@@ -1080,14 +1080,10 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.execSuccess === 'maingrid') {
-        _btn.execSuccess = 'mainline'
       }
 
       if (_btn.execError === 'equaltab') {
         _btn.execError = 'grid'
-      } else if (_btn.execError === 'maingrid') {
-        _btn.execError = 'mainline'
       }
 
       if (_btn.popClose === 'equaltab') {
@@ -1097,8 +1093,6 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.popClose === 'maingrid') {
-        _btn.popClose = 'mainline'
       }
 
       if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
diff --git a/src/templates/modalconfig/checkCard/index.jsx b/src/templates/modalconfig/checkCard/index.jsx
index 0813fd3..1bc351c 100644
--- a/src/templates/modalconfig/checkCard/index.jsx
+++ b/src/templates/modalconfig/checkCard/index.jsx
@@ -15,7 +15,7 @@
   }
 
   getCards = () => {
-    const { display, width, options, fields, ratio, picratio, backgroundColor } = this.props.config
+    const { display, width, options, fields, ratio, picratio, backgroundColor, field, labelShow } = this.props.config
 
     let _options = []
     let _fields = fields || []
@@ -86,7 +86,7 @@
         return <Col span={width}>
           <div className="card-cell no-margin-bottom" style={style}>
             <div className="bg-mask" style={_style}></div>
-            <span style={{color: '#000000', fontSize: '14px', height: '21px'}}>绀轰緥</span>
+            <span style={{color: '#000000', fontSize: '14px', height: '21px'}}>绀轰緥 {labelShow === 'false' ? field : ''}</span>
           </div>
         </Col>
       }
diff --git a/src/templates/modalconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx
index dcd142a..da672eb 100644
--- a/src/templates/modalconfig/dragelement/card.jsx
+++ b/src/templates/modalconfig/dragelement/card.jsx
@@ -138,7 +138,7 @@
   } else if (card.type === 'formula') {
     formItem = <div style={{marginTop: '8px', color: 'rgba(0, 0, 0, 0.85)', lineHeight: '1.5', ...card.style}}>{card.formula}{card.postfix || ''}</div>
   } else if (card.type === 'split') {
-    formItem = <div className="split-line" style={card.style}>{card.label}</div>
+    formItem = <div className="split-line" style={card.style}>{card.label}{showField && card.supField ? <span style={{color: '#8E44AD'}}>{`锛堜笂绾�${card.supField}锛塦}</span> : null}</div>
   } else if (card.type === 'vercode') {
     formItem = <Input style={{marginTop: '4px'}} placeholder={card.placeholder || ''} value={card.initval} addonAfter={
       <Button type="link" style={{padding: 0}} size="small">
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index c8b2d92..3f2571f 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -264,7 +264,7 @@
         })
       }
 
-      if (item.type === 'switch' || item.type === 'check') {
+      if (['switch', 'check', 'popSelect'].includes(item.type)) {
         _linksupFields.push({
           field: item.field,
           label: item.label
diff --git a/src/templates/modalconfig/index.scss b/src/templates/modalconfig/index.scss
index 9325eb1..18d34f1 100644
--- a/src/templates/modalconfig/index.scss
+++ b/src/templates/modalconfig/index.scss
@@ -172,12 +172,6 @@
         padding: 10px;
         cursor: pointer;
       }
-      .paste-Icon {
-        position: absolute;
-        font-size: 16px;
-        right: 15px;
-        top: 65px;
-      }
     }
   }
   .setting {
diff --git a/src/templates/modalconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx
index 4ac0090..7baf400 100644
--- a/src/templates/modalconfig/settingform/index.jsx
+++ b/src/templates/modalconfig/settingform/index.jsx
@@ -347,8 +347,13 @@
               )}
             </Form.Item>
           </Col> : null}
-          {display === 'drawer' && appType !== 'mob' ? <Col span={12}>
-            <Form.Item label="琛ㄥ崟绫诲瀷">
+          {appType !== 'mob' && (display === 'drawer' || display === 'modal') ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="閫夋嫨鏌ョ湅鏃惰〃鍗曞潎涓哄彧璇伙紝浠呯敤浜庢暟鎹睍绀恒��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                琛ㄥ崟绫诲瀷
+              </Tooltip>
+            }>
               {getFieldDecorator('formType', {
                 initialValue: config.setting.formType || 'edit'
               })(
@@ -359,6 +364,20 @@
               )}
             </Form.Item>
           </Col> : null}
+          {display === 'prompt' ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鎻愮ず妗嗙殑纭鎻愮ず淇℃伅銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                纭鎻愮ず
+              </Tooltip>
+            }>
+              {getFieldDecorator('tipTitle', {
+                initialValue: config.setting.tipTitle || ''
+              })(
+                <Input autoComplete="off" onPressEnter={this.handleSubmit} />
+              )}
+            </Form.Item>
+          </Col> : null}
           {!this.props.isSubTab && !appType && this.state.viewType !== 'popview' && display === 'modal' ? <Col span={12}>
             <Form.Item label="鎸傝浇瀵硅薄">
               {getFieldDecorator('container', {
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index 3e9c1ae..e163b1c 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -13,7 +13,7 @@
 
 const { TextArea } = Input
 const actionTypeOptions = {
-  pop: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'tipTitle', 'hidden'],
+  pop: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'hidden'],
   prompt: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'tipTitle', 'hidden'],
   exec: ['label', 'position', 'OpenType', 'intertype', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'openmenu', 'output', 'hidden'],
   excelIn: ['label', 'Ot', 'OpenType', 'intertype', 'icon', 'class', 'sheet', 'execSuccess', 'execError', 'hidden'],
diff --git a/src/templates/sharecomponent/actioncomponent/formconfig.jsx b/src/templates/sharecomponent/actioncomponent/formconfig.jsx
index 0476049..79f1290 100644
--- a/src/templates/sharecomponent/actioncomponent/formconfig.jsx
+++ b/src/templates/sharecomponent/actioncomponent/formconfig.jsx
@@ -64,13 +64,11 @@
     }
     refresh.push({
       value: 'maingrid',
-      text: '鍒锋柊涓昏〃锛堣锛�'
+      text: '鍒锋柊涓昏〃'
     }, {
       value: 'equaltab',
       text: '鍒锋柊鍚岀骇鏍囩'
     })
-  } else if (card.execSuccess === 'maingrid') {
-    card.execSuccess = 'grid'
   }
 
   if (card.OpenType === 'blank') {
@@ -523,7 +521,7 @@
       key: 'tipTitle',
       label: '纭鎻愮ず',
       initVal: card.tipTitle || '',
-      tooltip: '娉細寮圭獥锛堣〃鍗曪級鍦ㄦ樉绀轰负鏄惁妗嗘椂鏈夋晥銆�',
+      tooltip: '鎻愮ず妗嗙殑纭鎻愮ず淇℃伅銆�',
       required: false
     },
     {
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index 85b9d3f..e63f73f 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -278,12 +278,12 @@
         <Row gutter={24}>
           {!type && btn.sheet ? <Col span={8}>
             <Form.Item label="琛ㄥ悕" style={{whiteSpace: 'nowrap', margin: 0}}>
-              {btn.sheet}锛堣〃鍙橀噺璇蜂娇鐢�#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')}锛�
+              {btn.sheet}锛堜复鏃惰〃璇蜂娇鐢�#{btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')}锛�
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index 3bba3de..c58226f 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -716,39 +716,46 @@
         if (!err) {
           let _verify = {...verify, ...values}
 
-          if (_verify.excelHandle !== 'true') {
+          if (_verify.excelHandle !== 'true') { 
             delete _verify.excel_func
+          }
+          if (_verify.default === 'false' && _verify.scripts.length === 0) {
+            notification.warning({
+              top: 92,
+              message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒',
+              duration: 5
+            })
+            return
           }
 
           let cols = _verify.columns.map(col => col.Column.toLowerCase())
           cols = Array.from(new Set(cols))
+          let error = ''
 
           if (_verify.columns.length === 0) {
-            notification.warning({
-              top: 92,
-              message: '璇疯缃瓻xcel鍒楀瓧娈�!',
-              duration: 5
-            })
-            return
+            error = '璇疯缃瓻xcel鍒楀瓧娈�!'
           } else if (_verify.columns.length > cols.length) {
-            notification.warning({
-              top: 92,
-              message: 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!',
-              duration: 5
-            })
-            return
+            error = 'Excel鍒楀瓧娈靛悕锛屼笉鍙噸澶�!'
+          } else if (cols.includes('bid')) {
+            error = 'bid瀛楁涓轰繚鐣欏瓧锛屼笉鍙娇鐢�!'
+          } else if (cols.includes('jskey')) {
+            error = 'jskey瀛楁涓轰繚鐣欏瓧锛屼笉鍙娇鐢�!'
           } else if (_verify.range === 1) {
             let tEmptys = _verify.columns.filter(op => !op.Text)
             if (tEmptys.length > 0) {
-              notification.warning({
-                top: 92,
-                message: '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�',
-                duration: 5
-              })
-              return
+              error = '蹇界暐棣栬鏃讹紝浼氫娇鐢═ext鍊兼牎楠孍xcel棣栬鍐呭锛孴ext鍊间笌Excel琛ㄩ琛屽唴瀹圭浉鍚岋紝涓斿潎涓嶅彲涓虹┖锛�'
             }
           }
 
+          if (error) {
+            notification.warning({
+              top: 92,
+              message: error,
+              duration: 5
+            })
+            return
+          }
+
           _verify.columns.sort((a, b) => {
             if (a.import === 'init' && b.import !== 'init') {
               return 1
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
index 120f02d..b73e55b 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.scss
@@ -83,10 +83,6 @@
   .custom-table .ant-empty {
     margin: 20px 8px!important;
   }
-  .excel-custom-table {
-    position: relative;
-    top: -25px;
-  }
   .errorval {
     display: inline-block;
     width: 30px;
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
index 444e507..b7645c9 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/customscript/index.jsx
@@ -9,6 +9,7 @@
 import Utils from '@/utils/utils.js'
 import { checkSQL, getSearchFields } from '@/utils/utils-custom.js'
 import CodeMirror from '@/templates/zshare/codemirror'
+import MKEmitter from '@/utils/events.js'
 // import './index.scss'
 
 class CustomForm extends Component {
@@ -134,6 +135,9 @@
               loading: false,
               editItem: null
             })
+            if (values.uuid) {
+              MKEmitter.emit('editLineId', values.uuid)
+            }
             this.props.form.setFieldsValue({
               sql: ' '
             })
@@ -206,14 +210,14 @@
           </Col>
           <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, 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={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>
-              {usefulfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鎼滅储鏉′欢锛岃鎸夌収@xxx@鏍煎紡浣跨敤銆�'}>,&nbsp;{usefulfields}</Tooltip> : null}
+              <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}
             </Form.Item>
           </Col>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
index 1e04573..02f31bc 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/datasource/index.jsx
@@ -248,6 +248,18 @@
             </Col> : null}
             {btnType !== 'print' && excelHandle !== 'true' ? <Col span={8}>
               <Form.Item label={
+                <Tooltip placement="topLeft" title="瀵煎嚭excel鐨勬枃浠跺悕锛岄粯璁や负鑿滃崟鍚�+缁勪欢鍚嶃��">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鏂囦欢鍚�
+                </Tooltip>
+              }>
+                {getFieldDecorator('excelName', {
+                  initialValue: setting.excelName || ''
+                })(<Input autoComplete="off" />)}
+              </Form.Item>
+            </Col> : null}
+            {btnType !== 'print' && excelHandle !== 'true' ? <Col span={8}>
+              <Form.Item label={
                 <Tooltip placement="topLeft" title="瀵煎嚭excel涓伐浣滆〃鍚嶇О锛岄粯璁や负Sheet1銆�">
                   <QuestionCircleOutlined className="mk-form-tip" />
                   宸ヤ綔琛�
@@ -255,7 +267,7 @@
               }>
                 {getFieldDecorator('sheet', {
                   initialValue: setting.sheet || ''
-                })(<Input placeholder="" autoComplete="off" />)}
+                })(<Input autoComplete="off" />)}
               </Form.Item>
             </Col> : null}
             {btnType !== 'print' && excelHandle !== 'true' ? <Col span={8}>
@@ -286,7 +298,7 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {btnType !== 'print' && excelHandle !== 'true' ? <Col span={8}>
+            {/* {btnType !== 'print' && excelHandle !== 'true' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="Excel鍐呭鍖烘槸鍚﹁嚜鍔ㄦ崲琛屻��">
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -301,7 +313,7 @@
                   <Radio value="true">鏄�</Radio>
                 </Radio.Group>)}
               </Form.Item>
-            </Col> : null}
+            </Col> : null} */}
           </Row>
         </Form>
       </div>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 21d53fe..7b23dda 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -9,6 +9,7 @@
 import Utils from '@/utils/utils.js'
 import SettingUtils from './utils.jsx'
 import ColumnForm from './columnform'
+import OtherForm from './otherform'
 import DataSource from './datasource'
 import CustomScript from './customscript'
 import asyncComponent from '@/utils/asyncComponent'
@@ -30,6 +31,8 @@
     verify: {},
     debugId: '',
     activeKey: 'setting',
+    visible: false,
+    line: null,
     searchKey: '',
     excelColumns: [
       {
@@ -68,7 +71,7 @@
         editable: true,
         required: false,
         keyCol: true,
-        width: '8%',
+        width: '10%',
         render: (text) => {
           if (text === 'image') {
             return '鍥剧墖'
@@ -115,50 +118,50 @@
           {value: 'false', text: '鍚�'}
         ]
       },
-      {
-        title: '鍙栫粷瀵瑰��',
-        dataIndex: 'abs',
-        inputType: 'radio',
-        editable: true,
-        required: false,
-        keyVals: ['number'],
-        width: '10%',
-        render: (text, record) => {
-          if (record.type !== 'number') return ''
+      // {
+      //   title: '鍙栫粷瀵瑰��',
+      //   dataIndex: 'abs',
+      //   inputType: 'radio',
+      //   editable: true,
+      //   required: false,
+      //   keyVals: ['number'],
+      //   width: '10%',
+      //   render: (text, record) => {
+      //     if (record.type !== 'number') return ''
 
-          if (text === 'true') {
-            return '鏄�'
-          } else {
-            return '鍚�'
-          }
-        },
-        options: [
-          {value: 'true', text: '鏄�'},
-          {value: 'false', text: '鍚�'}
-        ]
-      },
-      {
-        title: '0鍊煎鍑�',
-        dataIndex: 'noValue',
-        inputType: 'radio',
-        editable: true,
-        required: false,
-        keyVals: ['number'],
-        width: '10%',
-        render: (text, record) => {
-          if (record.type !== 'number') return ''
+      //     if (text === 'true') {
+      //       return '鏄�'
+      //     } else {
+      //       return '鍚�'
+      //     }
+      //   },
+      //   options: [
+      //     {value: 'true', text: '鏄�'},
+      //     {value: 'false', text: '鍚�'}
+      //   ]
+      // },
+      // {
+      //   title: '0鍊煎鍑�',
+      //   dataIndex: 'noValue',
+      //   inputType: 'radio',
+      //   editable: true,
+      //   required: false,
+      //   keyVals: ['number'],
+      //   width: '10%',
+      //   render: (text, record) => {
+      //     if (record.type !== 'number') return ''
 
-          if (text !== 'false') {
-            return '鏄�'
-          } else {
-            return '鍚�'
-          }
-        },
-        options: [
-          {value: 'true', text: '鏄�'},
-          {value: 'false', text: '鍚�'}
-        ]
-      },
+      //     if (text !== 'false') {
+      //       return '鏄�'
+      //     } else {
+      //       return '鍚�'
+      //     }
+      //   },
+      //   options: [
+      //     {value: 'true', text: '鏄�'},
+      //     {value: 'false', text: '鍚�'}
+      //   ]
+      // },
       {
         title: '灏忔暟浣�',
         dataIndex: 'decimal',
@@ -170,7 +173,68 @@
         keyVals: ['number'],
         width: '12%',
         render: (text, record) => record.type === 'number' ? text : ''
-      }
+      },
+      {
+        title: '鍏朵粬',
+        dataIndex: 'other',
+        required: false,
+        width: '18%',
+        render: (_, record) => {
+          if (record.type === 'number') {
+            let val = ''
+
+            if (record.abs === 'true') {
+              val += '鍙栫粷瀵瑰�硷紱'
+            }
+            if (record.noValue === 'false') {
+              val += '0鍊间笉瀵煎嚭锛�'
+            }
+            if (record.format) {
+              if (record.format === 'thdSeparator') {
+                val += '鏍煎紡鍖栵細鍗冨垎浣嶏紱'
+              } else if (record.format === 'thdSepPm') {
+                val += '鏍煎紡鍖栵細鍗冨垎浣嶏紙璐熷�肩孩鑹诧級锛�'
+              } else if (record.format === 'percent') {
+                val += '鏍煎紡鍖栵細鐧惧垎姣旓紱'
+              }
+            }
+            if (record.prefix) {
+              val += `鍓嶇紑锛�${record.prefix}锛沗
+            }
+            if (record.postfix) {
+              val += `鍚庣紑锛�${record.postfix}锛沗
+            }
+
+            return <div>{val}<EditOutlined className="edit-other" onClick={() => {this.setState({visible: true, line: fromJS(record).toJS()})}} /></div>
+          } else if (record.type === 'text') {
+            let val = ''
+
+            if (record.wrapText === 'true') {
+              val += '鑷姩鎹㈣锛�'
+            }
+            if (record.noValue === 'false') {
+              val += '绌哄�间笉瀵煎嚭锛�'
+            }
+            if (record.textFormat) {
+              if (record.textFormat === 'YYYY-MM-DD') {
+                val += '鏍煎紡鍖栵細YYYY-MM-DD锛�'
+              } else if (record.textFormat === 'YYYY-MM-DD HH:mm:ss') {
+                val += '鏍煎紡鍖栵細YYYY-MM-DD HH:mm:ss锛�'
+              }
+            }
+            if (record.prefix) {
+              val += `鍓嶇紑锛�${record.prefix}锛沗
+            }
+            if (record.postfix) {
+              val += `鍚庣紑锛�${record.postfix}锛沗
+            }
+
+            return <div>{val}<EditOutlined className="edit-other" onClick={() => {this.setState({visible: true, line: fromJS(record).toJS()})}} /></div>
+          }
+
+          return ''
+        }
+      },
     ],
     scriptsColumns: [
       {
@@ -227,12 +291,12 @@
         dataIndex: 'operation',
         render: (text, record) =>
           (<div style={{textAlign: 'center'}}>
-            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
-            <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+            <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, 'scripts')
+              onConfirm={() => this.handleDelete(record)
             }>
               <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
             </Popconfirm>
@@ -392,14 +456,9 @@
     })
   }
 
-  handleEdit = (record, type) => {
-    let node = null
-
-    if (type === 'scripts') {
-      this.scriptsForm.edit(record)
-      node = document.getElementById('mk-exout-script')
-    }
-
+  handleEdit = (record) => {
+    this.scriptsForm.edit(record)
+    let node = document.getElementById('mk-exout-script')
 
     if (node && node.scrollTop) {
       let inter = Math.ceil(node.scrollTop / 10)
@@ -415,19 +474,17 @@
     }
   }
 
-  handleStatus = (record, type) => {
+  handleStatus = (record) => {
     let verify = JSON.parse(JSON.stringify(this.state.verify))
     record.status = record.status === 'false' ? 'true' : 'false'
 
-    if (type === 'scripts') {
-      verify.scripts = verify.scripts.map(item => {
-        if (item.uuid === record.uuid) {
-          return record
-        } else {
-          return item
-        }
-      })
-    }
+    verify.scripts = verify.scripts.map(item => {
+      if (item.uuid === record.uuid) {
+        return record
+      } else {
+        return item
+      }
+    })
 
     this.setState({
       verify: verify
@@ -459,38 +516,12 @@
     })
   }
 
-  handleDelete = (record, type) => {
-    const { verify } = this.state
+  handleDelete = (record) => {
+    let verify = JSON.parse(JSON.stringify(this.state.verify))
 
-    verify.columns = verify.columns.filter(item => item.uuid !== record.uuid)
+    verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
 
     this.setState({ verify: verify })
-  }
-
-  handleUpDown = (record, type, direction) => {
-    let verify = JSON.parse(JSON.stringify(this.state.verify))
-    let index = 0
-
-    verify.columns = verify.columns.filter((item, i) => {
-      if (item.uuid === record.uuid) {
-        index = i
-      }
-
-      return item.uuid !== record.uuid
-    })
-    if ((index === 0 && direction === 'up') || (index === verify.columns.length && direction === 'down')) {
-      return
-    }
-
-    if (direction === 'up') {
-      verify.columns.splice(index - 1, 0, record)
-    } else {
-      verify.columns.splice(index + 1, 0, record)
-    }
-
-    this.setState({
-      verify: verify
-    })
   }
 
   showError = (errorType) => {
@@ -626,7 +657,7 @@
                 loading: false
               })
               reject()
-            }, verify.scripts)
+            }, verify.scripts, 'submit')
           })
         })
       } else if (activeKey === 'columns') {
@@ -645,7 +676,7 @@
               loading: false
             })
             reject()
-          }, verify.scripts)
+          }, verify.scripts, 'submit')
         }
       } else if (activeKey === 'scripts') {
         this.setState({loading: true})
@@ -659,7 +690,7 @@
             loading: false
           })
           reject()
-        }, verify.scripts)
+        }, verify.scripts, 'submit')
       } else {
         resolve(verify)
       }
@@ -812,27 +843,30 @@
           col.type = 'text'
         }
       }
+      if (col.type === 'text' && col.format) {
+        delete col.format
+      } else if (col.type === 'number' && col.textFormat) {
+        delete col.textFormat
+      }
 
       return col
     })
-    // if (columns[0] && !['image', 'text', 'number'].includes(columns[0].type)) {
-    //   columns = columns.map(col => {
-    //     let _cell = {
-    //       uuid: Utils.getuuid(),
-    //       Column: col.Column,
-    //       Text: col.Text,
-    //       Width: 20,
-    //       abs: 'false',
-    //       output: col.output || 'true',
-    //       required: col.required || 'false',
-    //       type: 'text',
-    //     }
-
-    //     return _cell
-    //   })
-    // }
 
     this.setState({verify: {...verify, columns}})
+  }
+
+  lineSubmit = () => {
+    const { line, verify } = this.state
+
+    let columns = verify.columns.map(col => {
+      if (col.uuid === line.uuid) {
+        return line
+      }
+
+      return col
+    })
+
+    this.setState({verify: {...verify, columns}, line: null, visible: false})
   }
 
   // 鏍囩鍒囨崲
@@ -956,7 +990,7 @@
     }
   }
 
-  sqlverify = (_resolve, _reject, scripts) => {
+  sqlverify = (_resolve, _reject, scripts, type) => {
     const { searches, verify, debugId } = this.state
 
     if (verify.dataType !== 'custom') {
@@ -978,10 +1012,24 @@
         this.setState({debugId: _debugId})
         _resolve()
       } else {
-        _reject()
-        Modal.error({
-          title: result.message
-        })
+        if (type === 'submit') {
+          Modal.confirm({
+            title: result.message,
+            okText: '鐭ラ亾浜�',
+            cancelText: '寮哄埗淇濆瓨',
+            onOk: () => {
+              _reject()
+            },
+            onCancel() {
+              _resolve()
+            }
+          })
+        } else {
+          _reject()
+          Modal.error({
+            title: result.message
+          })
+        }
       }
     })
   }
@@ -1007,7 +1055,7 @@
 
   render() {
     const { card } = this.props
-    const { verify, excelColumns, scriptsColumns, activeKey, loading, searches, searchKey } = this.state
+    const { verify, excelColumns, scriptsColumns, activeKey, loading, searches, searchKey, visible, line } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -1040,7 +1088,7 @@
             <Button className="excel-col-add mk-red" title="娓呯┖Excel鍒�" onClick={this.clearField}>
               娓呯┖Excel鍒�
             </Button>
-            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>濡傞渶瀵煎嚭搴忓彿锛岃浣跨敤瀛楁 $Index锛涙暟鍊肩被鍨嬪鍑烘椂鍙彇缁濆鍊间互鍙婅缃皬鏁颁綅锛涘鍑轰负鍚︽椂锛屼笉浣跨敤琛屼俊鎭紱绾㈣壊鏍囬瀵煎嚭鏃跺垪澶存枃瀛椾负绾㈣壊銆�</div>
+            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>濡傞渶瀵煎嚭搴忓彿锛岃浣跨敤瀛楁 $Index锛涘鍑轰负鍚︽椂锛屼笉浣跨敤琛屼俊鎭紙鏂囨湰涓虹┖锛屾暟鍊间负0锛夛紱绾㈣壊鏍囬瀵煎嚭鏃跺垪澶存枃瀛椾负绾㈣壊銆�</div>
             <EditTable actions={['edit', 'move', 'copy', 'del']} type="excelcolumn" searchKey={searchKey} wrappedComponentRef={(inst) => this.columnRef = inst} data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
           </TabPane>
           {card.intertype === 'system' ? <TabPane tab={
@@ -1159,6 +1207,18 @@
             </Form>
           </TabPane>
         </Tabs>
+        <Modal
+          title=""
+          visible={visible}
+          width={1000}
+          maskClosable={false}
+          closable={false}
+          onOk={this.lineSubmit}
+          onCancel={() => {this.setState({visible: false, line: null})}}
+          destroyOnClose
+        >
+          <OtherForm line={line} submit={this.lineSubmit} onChange={(values) => this.setState({line: values})}/>
+        </Modal>
       </div>
     )
   }
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss
index f96c1d1..dd96816 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.scss
@@ -96,6 +96,15 @@
     padding: 0 5px;
     cursor: pointer;
   }
+  .edit-other {
+    opacity: 0;
+    color: #1890ff;
+    padding: 0 5px;
+    transition: opacity 0.2s;
+  }
+  tr:not([draggable="false"]) td:hover .edit-other {
+    opacity: 1;
+  }
 }
 .verify-excelout-box-tab {
   >.ant-spin {
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.jsx
new file mode 100644
index 0000000..9d79e04
--- /dev/null
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.jsx
@@ -0,0 +1,132 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Radio, Tooltip, Select, Input } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+// import './index.scss'
+
+class ExcelOutOtherColumn extends Component {
+  static propTpyes = {
+    onChange: PropTypes.func
+  }
+
+  onChange = (key, val) => {
+    const { line } = this.props
+
+    this.props.onChange({...line, [key]: val})
+  }
+
+  render() {
+    const { getFieldDecorator } = this.props.form
+    const { line } = this.props
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout} style={{minHeight: '100px', paddingTop: '10px'}}>
+        <Row gutter={24}>
+          {line.type === 'number' ? <Col span={8}>
+            <Form.Item label="鍙栫粷瀵瑰��">
+              {getFieldDecorator('abs', {
+                initialValue: line.abs || 'false'
+              })(
+                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.onChange('abs', e.target.value)}}>
+                  <Radio value="true">鏄�</Radio>
+                  <Radio value="false">鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {line.type === 'text' ? <Col span={8}>
+            <Form.Item label="鑷姩鎹㈣">
+              {getFieldDecorator('wrapText', {
+                initialValue: line.wrapText || 'false'
+              })(
+                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.onChange('wrapText', e.target.value)}}>
+                  <Radio value="true">鏄�</Radio>
+                  <Radio value="false">鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={8}>
+            <Form.Item label={line.type === 'number' ? '0鍊�' : 
+              <Tooltip placement="topLeft" title="鏃堕棿灏忎簬 1949-10-02 鏃躲��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                绌哄��
+              </Tooltip>
+            }>
+              {getFieldDecorator('noValue', {
+                initialValue: line.noValue || 'true'
+              })(
+                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.onChange('noValue', e.target.value)}}>
+                  <Radio value="true">瀵煎嚭</Radio>
+                  <Radio value="false">涓嶅鍑�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          {line.type === 'number' ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="浣跨敤鏍煎紡鍖栨椂锛岄渶璁剧疆灏忔暟浣嶃��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏍煎紡鍖�
+              </Tooltip>
+            }>
+              {getFieldDecorator('format', {
+                initialValue: line.format || ''
+              })(
+                <Select onChange={(val) => this.onChange('format', val)}>
+                  <Select.Option value=""> 鏃� </Select.Option>
+                  <Select.Option value="thdSeparator"> 鍗冨垎浣� </Select.Option>
+                  <Select.Option value="thdSepPm"> 鍗冨垎浣嶏紙璐熷�肩孩鑹诧級 </Select.Option>
+                  <Select.Option value="percent"> 鐧惧垎姣� </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {line.type === 'text' ? <Col span={8}>
+            <Form.Item label="鏍煎紡鍖�">
+              {getFieldDecorator('textFormat', {
+                initialValue: line.textFormat || ''
+              })(
+                <Select onChange={(val) => this.onChange('textFormat', val)}>
+                  <Select.Option value=""> 鏃� </Select.Option>
+                  <Select.Option value="YYYY-MM-DD"> YYYY-MM-DD </Select.Option>
+                  <Select.Option value="YYYY-MM-DD HH:mm:ss"> YYYY-MM-DD HH:mm:ss </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={8}>
+            <Form.Item label="鍓嶇紑">
+              {getFieldDecorator('prefix', {
+                initialValue: line.prefix || ''
+              })(
+                <Input autoComplete="off" onChange={(e) => this.onChange('prefix', e.target.value)} onPressEnter={this.props.submit}/>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={8}>
+            <Form.Item label="鍚庣紑">
+              {getFieldDecorator('postfix', {
+                initialValue: line.postfix || ''
+              })(
+                <Input autoComplete="off" onChange={(e) => this.onChange('postfix', e.target.value)} onPressEnter={this.props.submit}/>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(ExcelOutOtherColumn)
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/shareLink/index.scss b/src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.scss
similarity index 100%
copy from src/tabviews/zshare/actionList/shareLink/index.scss
copy to src/templates/sharecomponent/actioncomponent/verifyexcelout/otherform/index.scss
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
index 7df803d..f4e335c 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -15,9 +15,9 @@
 
     let arr_field = []
     verify.columns.forEach(item => {
-      if (item.Column !== '$Index') {
-        arr_field.push(item.Column)
-      }
+      if (item.output === 'false' || item.Column === '$Index') return
+      
+      arr_field.push(item.Column)
     })
     arr_field = arr_field.join(',')
 
diff --git a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss
index c26f463..457bdae 100644
--- a/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss
+++ b/src/templates/sharecomponent/actioncomponent/verifymegvii/index.scss
@@ -9,11 +9,6 @@
     word-wrap: break-word;
     word-break: break-word;
   }
-
-  .excel-custom-table {
-    position: relative;
-    top: -25px;
-  }
   .errorval {
     display: inline-block;
     width: 30px;
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
index ccad7dd..5e80f9d 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/index.jsx
@@ -97,12 +97,12 @@
         dataIndex: 'operation',
         render: (text, record) =>
           (<div style={{textAlign: 'center'}}>
-            <span className="operation-btn" title="缂栬緫" onClick={() => this.handleEdit(record, 'scripts')} style={{color: '#1890ff'}}><EditOutlined /></span>
-            <span className="operation-btn" title="鐘舵�佸垏鎹�" onClick={() => this.handleStatus(record, 'scripts')} style={{color: '#8E44AD'}}><SwapOutlined /></span>
+            <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, 'scripts')
+              onConfirm={() => this.handleDelete(record)
             }>
               <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
             </Popconfirm>
@@ -217,10 +217,10 @@
           _select.push(`@${_f.field}='1949-10-01'`)
         } else if (_f.type === 'number') {
           _type = `decimal(18,${_fieldlen})`
-          _select.push(`@${_f.field}=0`)
+          _select.push(`@${_f.field}=1`)
         } else if (_f.type === 'rate') {
           _type = `decimal(18,2)`
-          _select.push(`@${_f.field}=0`)
+          _select.push(`@${_f.field}=1`)
         } else {
           _select.push(`@${_f.field}=''`)
         }
@@ -245,8 +245,8 @@
         fieldArr.push(_f.field.toLowerCase())
         _usefulfields.push(_f.field)
 
-        if (/decimal/ig.test(_f.datatype)) {
-          _select.push(`@${_f.field}=0`)
+        if (/decimal|int/ig.test(_f.datatype)) {
+          _select.push(`@${_f.field}=1`)
         } else {
           _select.push(`@${_f.field}=''`)
         }
@@ -333,14 +333,9 @@
     })
   }
 
-  handleEdit = (record, type) => {
-    let node = null
-
-    if (type === 'scripts') {
-      this.scriptsForm.edit(record)
-      node = document.getElementById('mk-exout-script')
-    }
-
+  handleEdit = (record) => {
+    this.scriptsForm.edit(record)
+    let node = document.getElementById('mk-exout-script')
 
     if (node && node.scrollTop) {
       let inter = Math.ceil(node.scrollTop / 10)
@@ -356,6 +351,33 @@
     }
   }
 
+  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
+    })
+  }
+
+  handleDelete = (record) => {
+    let verify = fromJS(this.state.verify).toJS()
+
+    verify.scripts = verify.scripts.filter(item => item.uuid !== record.uuid)
+
+    this.setState({ verify: verify })
+
+    this.scriptsForm.check(record)
+  }
+
   showError = (errorType) => {
     if (errorType === 'S') {
       notification.success({
diff --git a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
index 60a1241..c33d899 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyprint/utils.jsx
@@ -34,8 +34,19 @@
       _dataresource = '(' + _dataresource + ') tb'
     }
 
+    let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
+
     // 姝e垯鏇挎崲
     let regoptions = [{
+      reg: new RegExp('@orderBy@', 'ig'),
+      value: setting.order || ''
+    }, {
+      reg: new RegExp('@pageSize@', 'ig'),
+      value: 10
+    }, {
+      reg: new RegExp('@pageIndex@', 'ig'),
+      value: 1
+    }, {
       reg: /@datam@/ig,
       value: `''`
     }, {
@@ -61,10 +72,10 @@
 
     // 鏁版嵁婧愬鐞�, 瀛樺湪鏄剧ず鍒楁椂 
     if (_dataresource) {
-      if (setting.order) {
-        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows`
-      } else {
+      if (custompage || !setting.order) {
         _dataresource = `/*system_query*/select ${arr_field} from ${_dataresource}`
+      } else {
+        _dataresource = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows`
       }
     }
 
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index 2886fa7..52d7eb1 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -332,6 +332,8 @@
             newcard.span = 24
             newcard.labelwidth = 16.2
           }
+        } else if (item.type === 'text') {
+          newcard.fieldlength = item.length || 50
         }
 
         items.push(newcard)
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
index db83147..0f771e9 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
@@ -120,11 +120,11 @@
     if (options.length === 0) {
       options = [{Value: '1', Text: '閫夐」1'}, {Value: '2', Text: '閫夐」2'}]
     }
-    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '36px'}}>
+    formItem = (<Radio.Group value={card.initval} style={{lineHeight: '36px', whiteSpace: 'nowrap'}}>
       {options.map((item, i) => (<Radio key={i} value={item.Value}> {item.Text} </Radio>))}
     </Radio.Group>)
   } else if (card.type === 'check') {
-    formItem = <Checkbox style={{lineHeight: '36px'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
+    formItem = <Checkbox style={{lineHeight: '36px', whiteSpace: 'nowrap'}} checked={card.initval === card.openVal}>{card.checkTip || ''}</Checkbox>
   } else if (card.type === 'range') {
     type = 'range-wrap'
     let vals = card.initval.split(',')
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 9d4b8f3..6380283 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -93,6 +93,7 @@
    * @description 鎼滅储鏉′欢缂栬緫锛岃幏鍙栨悳绱㈡潯浠惰〃鍗曚俊鎭�
    */
   handleSearch = (card) => {
+    const { config } = this.props
     const { searchlist } = this.state
     let linkableFields = []
 
@@ -108,8 +109,8 @@
     })
 
     let columns = null
-    if (this.props.config.type === 'table') {
-      columns = this.props.config.columns.map(item => {
+    if (config.columns && config.columns.length) {
+      columns = config.columns.map(item => {
         return {key: item.uuid, text: item.field, value: item.field, label: item.label}
       })
     }
@@ -209,7 +210,8 @@
           sqlVerifing: true
         })
 
-        let sql = res.dataSource
+        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+        ${res.dataSource}`
         sql = sql.replace(/@\$|\$@/ig, '')
 
         let rduri = ''
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index 52ac1b9..e91fee9 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -600,6 +600,9 @@
         if (this.record.type === 'select' || this.record.type === 'link') {
           extra = <span className="add-resource-empty" onClick={this.handleEmpty}>鍏ㄩ儴</span>
         }
+        if (item.placeholder) {
+          extra = <><span className="resource-public-var">{item.placeholder}</span>{extra}</>
+        }
 
         content = <CodeMirror />
       } else if (item.type === 'options') {
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.scss b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
index 1f9373d..6a66718 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.scss
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.scss
@@ -40,9 +40,15 @@
   .add-resource-empty {
     position: absolute;
     right: 10px;
-    top: -25px;
+    top: -22px;
     color: #1890ff;
     cursor: pointer;
     font-size: 14px;
   }
+  .resource-public-var {
+    position: absolute;
+    left: 0px;
+    top: -22px;
+    font-size: 14px;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/treepageconfig/updatetable/index.jsx b/src/templates/treepageconfig/updatetable/index.jsx
index cebb5ca..8de0cea 100644
--- a/src/templates/treepageconfig/updatetable/index.jsx
+++ b/src/templates/treepageconfig/updatetable/index.jsx
@@ -1121,14 +1121,10 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.execSuccess === 'maingrid') {
-        _btn.execSuccess = 'mainline'
       }
 
       if (_btn.execError === 'equaltab') {
         _btn.execError = 'grid'
-      } else if (_btn.execError === 'maingrid') {
-        _btn.execError = 'mainline'
       }
 
       if (_btn.popClose === 'equaltab') {
@@ -1138,8 +1134,6 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.popClose === 'maingrid') {
-        _btn.popClose = 'mainline'
       }
 
       if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx
index 50e6ad5..0286596 100644
--- a/src/templates/zshare/customscript/index.jsx
+++ b/src/templates/zshare/customscript/index.jsx
@@ -328,7 +328,7 @@
             </Col> : null}
             <Col span={16}>
               <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
-                ErrorCode, retmsg
+                errorcode, retmsg
               </Form.Item>
             </Col>
             <Col span={24} className="sqlfield">
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index c2a388a..50071ac 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -261,6 +261,7 @@
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
       tooltip: '鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆�',
       required: true
     },
     {
@@ -1794,6 +1795,19 @@
     },
     {
       type: 'radio',
+      key: 'notZero',
+      label: "涓嶅彲涓�0",
+      initVal: card.notZero || 'false',
+      options: [{
+        value: 'true',
+        text: '鏄�'
+      }, {
+        value: 'false',
+        text: '鍚�'
+      }]
+    },
+    {
+      type: 'radio',
       key: 'database',
       label: '鏁版嵁搴�',
       initVal: card.database || 'local',
@@ -1865,6 +1879,21 @@
       }, {
         value: 'false',
         text: '鍚�'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'format',
+      label: '鏍煎紡鍖�',
+      tooltip: '浣跨敤鍗冨垎浣嶆椂锛屾暟鍊煎皢浠ュ崈鍒嗕綅鏍煎紡鏄剧ず锛屾彁浜ゆ椂涓哄師鏁板�笺��',
+      initVal: card.format || '',
+      forbid: appType === 'mob',
+      options: [{
+        value: '',
+        text: '鏃�'
+      }, {
+        value: 'thdSeparator',
+        text: '鍗冨垎浣�'
       }]
     },
     {
@@ -2495,6 +2524,22 @@
       readonly: false
     },
     {
+      type: 'radio',
+      key: 'opacity',
+      label: '鏄惁鍙',
+      initVal: card.opacity || 'true',
+      tooltip: '涓嶅彲瑙佹椂浠呯敤浣滆〃鍗曞垎闅旓紝涓嶆樉绀哄悕绉般��',
+      required: false,
+      forbid: appType === 'mob',
+      options: [{
+        value: 'true',
+        text: '鍙'
+      }, {
+        value: 'false',
+        text: '涓嶅彲瑙�'
+      }]
+    },
+    {
       type: 'text',
       key: 'regularExtra',
       label: '姝e垯鎵╁睍绗�',
@@ -2571,7 +2616,7 @@
       key: 'enter',
       label: '鍥炶溅浜嬩欢',
       initVal: (card.type === 'text' || card.type === 'number') ? (card.enter || 'sub') : (card.enter || 'false'),
-      tooltip: '1銆佺偣鍑籈nter閿垨鏂囨湰绫昏〃鍗曡緭鍏ュ洖杞︾锛�2銆佷笅鎷夐�夋嫨鎴栧紑鍏崇殑閫夐」鍒囨崲銆�',
+      tooltip: '1銆佺偣鍑籈nter閿垨鏂囨湰绫昏〃鍗曡緭鍏ュ洖杞︾锛�2銆佷笅鎷夐�夋嫨銆佹椂闂淬�佸紑鍏崇殑閫夐」鍒囨崲銆�',
       options: [{
         value: 'sub',
         text: '鎻愪氦'
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 6f21e10..17b3585 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -21,7 +21,7 @@
 
 const modalTypeOptions = {
   text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant', 'mkfocus'],
-  number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom', 'mkfocus'],
+  number: ['initval', 'readonly', 'notZero', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom', 'mkfocus', 'format'],
   select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
   checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
   radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
@@ -31,15 +31,15 @@
   fileupload: ['readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'compress', 'miniSet', 'splitline', 'marginTop', 'marginBottom', 'maxSize'],
   switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'enter', 'splitline', 'marginTop', 'marginBottom'],
   check: ['initval', 'openVal', 'closeVal', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'marginTop', 'marginBottom', 'checkTip'],
-  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'place', 'marginTop', 'marginBottom', 'minDate', 'maxDate', 'precision'],
-  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'place', 'marginTop', 'marginBottom'],
+  date: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'declareType', 'mode', 'splitline', 'place', 'marginTop', 'marginBottom', 'minDate', 'maxDate', 'precision'],
+  datemonth: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'place', 'marginTop', 'marginBottom'],
   // datetime: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'declareType', 'mode', 'splitline', 'marginTop', 'marginBottom', 'minDate', 'maxDate'],
   textarea: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'span', 'labelwidth', 'maxRows', 'encryption', 'interception', 'tooltip', 'extra', 'place', 'count', 'placeholder', 'marginTop', 'marginBottom'],
   cascader: ['readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'marginTop', 'marginBottom', 'separator'],
   color: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'colorType', 'extra', 'marginTop', 'marginBottom'],
   rate: ['initval', 'readonly', 'required', 'hidden', 'readin', 'span', 'labelwidth', 'splitline', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'allowHalf', 'color', 'rateCount', 'character', 'place'],
   hint: ['label', 'field', 'type', 'blacklist', 'supField', 'message', 'span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
-  split: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', 'splitctrl', 'supField'],
+  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'],
   funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
@@ -243,6 +243,9 @@
         shows.push('unchecked')
       }
     } else if (['date', 'datemonth'].includes(type)) {
+      if (this.record.enter === 'tab' || this.record.enter === 'sub') {
+        shows.push('tabField')
+      }
       reOptions.initval = dateOptions[type]
       reTypes.initval = 'select'
       if (type === 'date') {
diff --git a/src/templates/zshare/pasteform/index.jsx b/src/templates/zshare/pasteform/index.jsx
index 3067ef0..73d666e 100644
--- a/src/templates/zshare/pasteform/index.jsx
+++ b/src/templates/zshare/pasteform/index.jsx
@@ -116,7 +116,7 @@
       <Form {...formItemLayout} className="config-paste-form">
         <Row gutter={24}>
           <Col span={24}>
-            <Form.Item label="閰嶇疆淇℃伅" className="textarea">
+            <Form.Item label="" className="textarea">
               {getFieldDecorator('config', {
                 initialValue: '',
                 rules: [
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index 44e887b..affd4f5 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -134,6 +134,8 @@
       error = '寮�鍚偖浠跺彂閫佹椂锛岄渶瑕侀�夋嫨閭欢妯℃澘锛�'
     } else if (verify.printEnable === 'true' && !verify.printTempId) {
       error = '浣跨敤鍗曟嵁鎵撳嵃鏃讹紝闇�瑕侀�夋嫨鎵撳嵃妯℃澘锛�'
+    } else if (verify.linkEnable === 'true' && !verify.linkUrl) {
+      error = '鎵撳紑閾炬帴寮�鍚椂锛岄渶瑕佹坊鍔犻摼鎺ュ湴鍧�锛�'
     } else if (verify.accountdate === 'true' && !verify.accountfield) {
       error = '寮�鍚处鏈熸椂锛岄渶瑕侀�夋嫨楠岃瘉鍏徃锛�'
     } else if (verify.preHandle === 'true' && !verify.pre_func) {
@@ -166,6 +168,10 @@
     }
     if (_verify.printEnable !== 'true') {
       _verify.printTempId = ''
+    }
+    if (_verify.linkEnable !== 'true') {
+      delete _verify.linkUrl
+      delete _verify.linkProUrl
     }
     if (_verify.accountdate !== 'true') {
       _verify.accountfield = ''
@@ -292,7 +298,7 @@
   }
 
   render() {
-    const { unionFields, verify, notes, emailCodes, card, appType, columns } = this.props
+    const { unionFields, verify, notes, emailCodes, card, appType, columns, fields } = this.props
     const { wxTemps, selectTemp } = this.state
     const formItemLayout = {
       labelCol: {
@@ -306,13 +312,29 @@
     }
 
     let _columns = []
-    if (window.GLOB.process) {
-      _columns = columns.filter(col => {
-        if (!col.field) return false
-        if (col.field.toLowerCase() === 'id') return false
-        if (col.type === 'text' && col.fieldlength > 100)  return false
+    let remarks = []
+    if (window.GLOB.process && card.intertype !== 'inner') {
+      let cols = []
+      fields.forEach(col => {
+        if (!col.field) return
+
+        cols.push(col.field.toLowerCase())
+        _columns.push(col)
+
+        if ((col.type === 'text' || col.type === 'textarea') && col.field !== 'BID') {
+          remarks.push(col)
+        }
+      })
+
+      columns.forEach(col => {
+        if (!col.field) return
+
+        let key = col.field.toLowerCase()
+
+        if (key === 'id' || cols.includes(key)) return
+        if (col.type === 'text' && col.fieldlength > 100)  return
   
-        return true
+        _columns.push(col)
       })
     }
 
@@ -524,7 +546,31 @@
             </Form.Item>
           </Col> : null}
           <Col span={24}></Col>
-          {window.GLOB.process ? <Col span={8}>
+          <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="鎸夐挳鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勯摼鎺ュ湴鍧�銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鎵撳紑閾炬帴
+              </Tooltip>
+            }>
+              <Radio.Group value={verify.linkEnable || 'false'} onChange={(e) => {this.onOptionChange(e.target.value, 'linkEnable')}}>
+                <Radio value="true">寮�鍚�</Radio>
+                <Radio value="false">涓嶅紑鍚�</Radio>
+              </Radio.Group>
+            </Form.Item>
+          </Col>
+          {verify.linkEnable === 'true' ? <Col span={24} className="dz-link">
+            <Form.Item label="閾炬帴鍦板潃" required>
+              <Input.TextArea autoComplete="off" value={verify.linkUrl || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'linkUrl')}}/>
+            </Form.Item>
+          </Col> : null}
+          {verify.linkEnable === 'true' ? <Col span={24} className="dz-link">
+            <Form.Item label="姝e紡鍦板潃">
+              <Input.TextArea autoComplete="off" value={verify.linkProUrl || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'linkProUrl')}}/>
+            </Form.Item>
+          </Col> : null}
+          <Col span={24}></Col>
+          {window.GLOB.process && card.intertype !== 'inner' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="bottomLeft" title="鍦ㄨ彍鍗曞紑鍚伐浣滄祦鏃舵湁鏁堛��">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -537,7 +583,7 @@
               </Radio.Group>
             </Form.Item>
           </Col> : null}
-          {window.GLOB.process && verify.workFlow === 'true' ? <Col span={8}>
+          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' ? <Col span={8}>
             <Form.Item label="绫诲瀷">
               <Radio.Group value={verify.flowType} onChange={(e) => {this.onOptionChange(e.target.value, 'flowType')}}>
                 <Radio value="start">鍙戣捣</Radio>
@@ -546,7 +592,7 @@
               </Radio.Group>
             </Form.Item>
           </Col> : null}
-          {window.GLOB.process && verify.workFlow === 'true' ? <Col span={8}>
+          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="bottomLeft" title="鎵ц浣嶇疆鍦ㄧ郴缁熼粯璁ql涔嬪悗銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -559,9 +605,9 @@
               </Radio.Group>
             </Form.Item>
           </Col> : null}
-          {window.GLOB.process && verify.workFlow === 'true' && verify.flowType === 'approval' ? <Col span={8}>
+          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' && verify.flowType === 'approval' ? <Col span={8}>
             <Form.Item label={
-              <Tooltip placement="bottomLeft" title="濡傛灉瀹℃壒瀛樺湪澶氭潯鍒嗘敮锛屽彲娣诲姞瀹℃壒娴佺▼鐨勬帶鍒跺瓧娈碉紝閫氳繃琛屼俊鎭帶鍒舵祦绋嬭蛋鍚戙�傛敞锛氶渶鍦ㄦ祦绋嬪浘涓畬鍠勫垎鏀殑鎵ц鏉′欢銆�">
+              <Tooltip placement="bottomLeft" title="濡傛灉瀹℃壒瀛樺湪澶氭潯鍒嗘敮锛屽彲娣诲姞瀹℃壒娴佺▼鐨勬帶鍒跺瓧娈碉紝閫氳繃琛ㄥ崟淇℃伅鎴栬淇℃伅鎺у埗娴佺▼璧板悜銆傛敞锛氶渶鍦ㄦ祦绋嬪浘涓畬鍠勫垎鏀殑鎵ц鏉′欢銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 娴佺▼鎺у埗
               </Tooltip>
@@ -575,6 +621,22 @@
               </Select>
             </Form.Item>
           </Col> : null}
+          {window.GLOB.process && card.intertype !== 'inner' && verify.workFlow === 'true' && verify.flowType !== 'start' ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="鍙�氳繃琛ㄥ崟瀛楁濉啓瀹℃壒鎴栭┏鍥炵殑澶囨敞淇℃伅銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                澶囨敞瀛楁
+              </Tooltip>
+            }>
+              <Select allowClear value={verify.flowRemark} onChange={(val) => {this.onOptionChange(val || '', 'flowRemark')}}>
+                {remarks.map(option =>
+                  <Select.Option key={option.field} value={option.field}>
+                    {option.label}
+                  </Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col> : null}
           <Col span={24}></Col>
           <Col span={8}>
             <Form.Item label={
diff --git a/src/templates/zshare/verifycard/baseform/index.scss b/src/templates/zshare/verifycard/baseform/index.scss
index 8625b9f..aec5f58 100644
--- a/src/templates/zshare/verifycard/baseform/index.scss
+++ b/src/templates/zshare/verifycard/baseform/index.scss
@@ -24,4 +24,14 @@
       }
     }
   }
+}
+.dz-link {
+  .ant-form-item {
+    .ant-form-item-label {
+      width: 10.8%;
+    }
+    .ant-form-item-control-wrapper {
+      width: 89.2%;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
index c0c0a6c..22d6853 100644
--- a/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
+++ b/src/templates/zshare/verifycard/callbackcustomscript/index.jsx
@@ -222,7 +222,7 @@
           </Col> : null}
           {!type ? <Col span={10}>
             <Form.Item label="鎶ラ敊瀛楁" style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
             </Form.Item>
           </Col> : null}
           {!type ? <Col span={24} className="sqlfield">
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index 0a068a3..05231cc 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -46,7 +46,7 @@
   }
 
   handleConfirm = () => {
-    const { type, workFlow, flowType, useDefaultSql, defaultsql } = this.props
+    const { type, workFlow, flowType, flowSql, flowRemark, useDefaultSql, defaultsql } = this.props
     const { editItem, skip } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
@@ -136,6 +136,51 @@
           `
         }
 
+        if (window.GLOB.process && workFlow === 'true' && flowSql === 'true') {
+          if (flowType === 'start') {
+            sql += `
+              /* 宸ヤ綔娴侀粯璁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 {
+            sql += `
+              /* 宸ヤ綔娴侀粯璁ql */
+              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${flowRemark ? ',remark=@' + 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${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@${flowRemark ? ',@' + flowRemark : ''}
+              
+              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
+            `
+          }
+        }
+
         sql += _backCustomScript + tail
 
         if (window.GLOB.funcs && window.GLOB.funcs.length > 0) {
@@ -163,10 +208,10 @@
           sql = sql.replace(/@check_type@/ig, `'瀹℃牳'`)
           sql = sql.replace(/@notice_type@/ig, `'鎶勯��'`)
 
-          if (flowType !== 'start') {
-            sql = sql.replace(/@check_userids@/ig, `'checkuserids'`)
-            sql = sql.replace(/@notice_userids@/ig, `'noticeuserids'`)
-          }
+          sql = sql.replace(/@check_userids@/ig, `''`)
+          sql = sql.replace(/@notice_userids@/ig, `''`)
+          
+          sql = sql.replace(/@works_flow_sign@/ig, `''`)
         }
         
         if (skip) {
@@ -216,7 +261,7 @@
   }
 
   selectScript = (value, option) => {
-    const { flowType } = this.props
+    const { flowType, flowRemark } = this.props
 
     if (!value || !option) return
 
@@ -234,18 +279,23 @@
       if (flowType === 'start') {
         value = `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,upid)
-        select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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@`
+        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 {
-        value = `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(),modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
+        value = `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${flowRemark ? ',remark=@' + 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,upid)
-        select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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@${flowRemark ? ',@' + flowRemark : ''}
+        
+        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
-              delete s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
               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)
@@ -253,7 +303,8 @@
         end
         if @notice_userids@ != ''
         begin
-              delete n
+              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
@@ -303,17 +354,17 @@
           </Col> : null}
           {!_type ? <Col span={10}>
             <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0, whiteSpace: 'nowrap'}}>
-              ErrorCode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, retmsg
+              errorcode锛堝鍔犲悗缂�NT琛ㄧず鏁版嵁涓嶅洖婊氾紝濡侲NT銆丯NT銆丗NT銆丯MNT銆丆NT銆�-2NT锛�, 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, 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="绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��"><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> : ''}
               {colfields ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="瀛楁闆嗗彉閲忥紝绯荤粺浼氬畾涔夊彉閲忓苟璧嬪�笺��">, {colfields}</Tooltip> : ''}
-              {window.GLOB.process && workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆傛敞锛歝heck_userids銆乶otice_userids 鍦ㄥ鎵规垨椹冲洖鏃舵湁鏁堛��">,<span style={{color: 'purple'}}> 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</span></Tooltip> : null}
             </Form.Item>
           </Col> : null}
           {!_type ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
@@ -367,7 +418,7 @@
           </Col>
           <Col span={24} className="sql">
             <Form.Item label={
-              <Tooltip placement="topLeft" overlayStyle={{width: '320px', maxWidth: '320px'}} title={<><div>{'璋冭瘯鏇挎崲绗� /*$breakpoint_begin_xxxx@ 銆丂breakpoint_end_xxxx$*/锛屽湪鎺у埗鍙颁腑杈撳叆 window.debug = \'xxxx\' 浼氬惎鐢ㄥ搴旂殑璋冭瘯璇彞锛屽揩鎹烽敭 ctrl+c 鎴栧湪鎺у埗鍙颁腑杈撳叆 window.debug = false 鍏抽棴璋冭瘯銆傛敞锛氳皟璇曟椂瀛楃 $breakpoint_proc@ 灏嗚鏇挎崲銆�'}</div><div style={{height: '5px'}}></div><div>{'鏁版嵁妫�鏌ユ浛鎹㈢ $check@ -> \'\'銆� @check$ -> \'\'锛孍rrorCode绛変簬C鏃朵細璇㈤棶鏄惁缁х画鎵ц锛岀‘瀹氭椂 $check@ -> /*銆� @check$ -> */銆傛敞锛�1銆侀渶浣跨敤绯荤粺鎺ュ彛 2銆佽璁剧疆涓衡�滈�夋嫨澶氳鈥濇椂鏃犳晥銆�'}</div></>}>
+              <Tooltip placement="topLeft" overlayStyle={{width: '520px', maxWidth: '520px'}} title={<><div>{`璋冭瘯鏇挎崲绗� /*$breakpoint_begin_xxxx@ 銆丂breakpoint_end_xxxx$*/锛屽湪鎺у埗鍙颁腑杈撳叆 window.debug = 'xxxx' 浼氬惎鐢ㄥ搴旂殑璋冭瘯璇彞锛屽揩鎹烽敭 ctrl+c 鎴栧湪鎺у埗鍙颁腑杈撳叆 window.debug = false 鍏抽棴璋冭瘯銆傛敞锛氳皟璇曟椂瀛楃 $breakpoint_proc@ 灏嗚鏇挎崲銆俙}</div><div style={{height: '5px'}}></div><div>{`鏁版嵁妫�鏌ユ浛鎹㈢ $check@ -> ''銆� @check$ -> ''锛孍rrorCode绛変簬C鏃朵細璇㈤棶鏄惁缁х画鎵ц锛岀‘瀹氭椂 $check@ -> /*銆� @check$ -> */銆傛敞锛�1銆侀渶浣跨敤绯荤粺鎺ュ彛 2銆佽璁剧疆涓衡�滈�夋嫨澶氳鈥濇椂鏃犳晥銆俙}</div><div style={{height: '5px'}}></div><div>{`鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''`}</div></>}>
                 <QuestionCircleOutlined className="mk-form-tip" />
                 sql
               </Tooltip>
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 4617c6c..8bc3126 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -649,12 +649,13 @@
     _verify.scripts = _verify.scripts || []
     _verify.cbScripts = _verify.cbScripts || []
 
-    if (window.GLOB.process) {
+    if (window.GLOB.process && card.intertype !== 'inner') {
       _verify.workFlow = _verify.workFlow || 'false'
       _verify.flowType = _verify.flowType || (card.sqlType === 'insert' ? 'start' : 'approval')
       _verify.flowSql = _verify.flowSql || 'true'
     } else {
       delete _verify.workFlow
+      delete _verify.flowRemark
       delete _verify.flowType
       delete _verify.flowSql
     }
@@ -774,13 +775,13 @@
         _select.push(`@${_f.field}='1949-10-01'`)
       } else if (_f.type === 'number') {
         _type = `decimal(18,${_fieldlen})`
-        _select.push(`@${_f.field}=0`)
+        _select.push(`@${_f.field}=1`)
       } else if (_f.declare === 'decimal') {
         _type = `decimal(18,${_f.decimal || 0})`
-        _select.push(`@${_f.field}=0`)
+        _select.push(`@${_f.field}=1`)
       } else if (_f.type === 'rate') {
         _type = `decimal(18,2)`
-        _select.push(`@${_f.field}=0`)
+        _select.push(`@${_f.field}=1`)
       } else {
         _select.push(`@${_f.field}=''`)
       }
@@ -816,8 +817,8 @@
         colfields.push(_f.field)
 
         if (_f.datatype) { // 鑷畾涔夊瓧娈�
-          if (/decimal/ig.test(_f.datatype)) {
-            _select.push(`@${_f.field}=0`)
+          if (/decimal|int/ig.test(_f.datatype)) {
+            _select.push(`@${_f.field}=1`)
           } else {
             _select.push(`@${_f.field}=''`)
           }
@@ -841,7 +842,7 @@
         }
 
         if (_f.type === 'number') {
-          _select.push(`@${_f.field}=0`)
+          _select.push(`@${_f.field}=1`)
         } else {
           _select.push(`@${_f.field}=''`)
         }
@@ -1562,7 +1563,7 @@
     
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
-      if ((card.sqlType === 'custom' || verify.default === 'false') && verify.scripts.length === 0) {
+      if ((card.sqlType === 'custom' || verify.default === 'false') && !(verify.workFlow === 'true' && verify.flowSql === 'true') && verify.scripts.length === 0) {
         notification.warning({
           top: 92,
           message: '涓嶆墽琛岄粯璁ql鏃讹紝蹇呴』璁剧疆鑷畾涔夎剼鏈紒',
@@ -1687,7 +1688,7 @@
               {verify.default === 'false' ? <span className="count-tip"><ExclamationOutlined style={{color: 'orange'}}/></span> : null}
             </span>
           } key="base">
-            <BaseForm card={card} appType={appType} columns={columns} unionFields={unionFields} verify={verify} notes={notes} emailCodes={emailCodes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
+            <BaseForm card={card} appType={appType} fields={fields} columns={columns} unionFields={unionFields} verify={verify} notes={notes} emailCodes={emailCodes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
           </TabPane> : null}
           {verifyInter === 'system' ? <TabPane tab={
             <span>
@@ -1777,6 +1778,10 @@
                 type="fullscreen"
                 btn={this.props.card}
                 initsql={this.state.initsql}
+                workFlow={verify.workFlow}
+                flowRemark={verify.flowRemark}
+                flowType={verify.flowType}
+                flowSql={verify.flowSql}
                 customScripts={verify.scripts}
                 useDefaultSql={verify.default !== 'false'}
                 defaultsql={this.state.defaultsql}
@@ -1791,7 +1796,9 @@
               btn={this.props.card}
               initsql={this.state.initsql}
               workFlow={verify.workFlow}
+              flowRemark={verify.flowRemark}
               flowType={verify.flowType}
+              flowSql={verify.flowSql}
               customScripts={verify.scripts}
               useDefaultSql={verify.default !== 'false'}
               defaultsql={this.state.defaultsql}
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index 9390ede..841817d 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -193,6 +193,42 @@
   }
 
   /**
+   * @description 鑾峰彇鎸囧畾缁勪欢
+   * @return {String}  缁勪欢id
+   */
+  static getComponent (Id) {
+    let interfaces = window.GLOB.customMenu.interfaces
+    let components = window.GLOB.customMenu.components
+    let cell = null
+
+    let mapComponents = (components = []) => {
+      components.forEach(item => {
+        if (item.uuid === Id) {
+          cell = item
+        }else if (item.type === 'tabs') {
+          item.subtabs.forEach(f_tab => {
+            mapComponents(f_tab.components)
+          })
+        } else if (item.type === 'group') {
+          mapComponents(item.components)
+        }
+      })
+    }
+
+    mapComponents(components)
+
+    if (!cell && interfaces) {
+      interfaces.forEach(m => {
+        if (m.uuid === Id && m.status === 'true') {
+          cell = m
+        }
+      })
+    }
+    
+    return cell
+  }
+
+  /**
    * @description 鑾峰彇涓婄骇妯″潡
    * @return {String}  selfId  褰撳墠缁勪欢id
    */
@@ -540,7 +576,16 @@
             return cell
           })
         }
-      } else if (item.type === 'table' && item.cols) {
+      } else if (item.type === 'table') {
+        if (item.supNodes && item.supNodes.length > 0) {
+          item.supNodes = item.supNodes.map(cell => {
+            cell.nodes = cell.nodes.map(n => md5(commonId + n))
+            cell.componentId = cell.nodes[cell.nodes.length - 1]
+
+            return cell
+          })
+        }
+
         let loopCol = (cols) => {
           return cols.map(col => {
             if (col.type === 'action') {
@@ -578,7 +623,7 @@
           })
         }
 
-        item.cols = loopCol(item.cols)
+        item.cols = loopCol(item.cols || [])
 
         if (item.colsCtrls) {
           item.colsCtrls = item.colsCtrls.map(col => {
@@ -846,7 +891,7 @@
           return cell
         })
       }
-    } else if (item.type === 'table' && item.cols) {
+    } else if (item.type === 'table') {
       let loopCol = (cols) => {
         return cols.map(col => {
           if (col.type === 'action') {
@@ -887,7 +932,7 @@
         })
       }
 
-      item.cols = loopCol(item.cols)
+      item.cols = loopCol(item.cols || [])
 
       if (item.colsCtrls) {
         item.colsCtrls = item.colsCtrls.map(col => {
@@ -1009,7 +1054,7 @@
       } else if (item.type === 'daterange') {
         value = '1949-10-01 00:00:00.000,1949-10-02 00:00:00.000'
       } else if (item.type === 'range') {
-        value = item.initval || `${item.minValue || '-999999'},${item.maxValue || '999999'}`
+        value = item.initval || `${item.minValue || '-999999999'},${item.maxValue || '999999999'}`
       } else if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) {
         type = 'multi'
       }
@@ -1058,7 +1103,7 @@
       searchText.push('(' + item.key + ' >= \'' + val[0] + '\' AND ' + item.key + ' < \'' + val[1] + '\')')
     } else if (item.type === 'range') {
       let val = item.value.split(',')
-      searchText.push('(' + item.key + ' >= ' + (val[0] || -999999) + ' AND ' + item.key + ' < ' + (val[1] || 999999) + ')')
+      searchText.push('(' + item.key + ' >= ' + (val[0] || -999999999) + ' AND ' + item.key + ' <= ' + (val[1] || 999999999) + ')')
     } else if (item.type === 'datemonth') {
       if (item.match === '=') {
         searchText.push('(' + item.key + ' = \'' + item.value + '\')')
@@ -1122,10 +1167,10 @@
       let val = item.value.split(',')
       options.push({
         reg: new RegExp('@' + item.key + '@', 'ig'),
-        value: `${val[0] || -999999}`
+        value: `${val[0] || -999999999}`
       }, {
         reg: new RegExp('@' + item.key + '1@', 'ig'),
-        value: `${val[1] || 999999}`
+        value: `${val[1] || 999999999}`
       })
     } else if (item.type === 'datemonth') {
       if (item.match === '=') {
@@ -1675,7 +1720,7 @@
       } else if (!card.setting.supModule) {
         errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
-    } else if (card.type === 'card' && card.subtype === 'datacard') { // 鏁版嵁鍗★紝鍙兘鏈夊涓婄骇
+    } else if ((card.type === 'card' && card.subtype === 'datacard') || card.subtype === 'normaltable') { // 鏁版嵁鍗°�乼able锛屽彲鑳芥湁澶氫笂绾�
       if (card.wrap.supType !== 'multi' && !card.setting.supModule) {
         errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index 91dfd4a..6210d62 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -1,16 +1,13 @@
 import md5 from 'md5'
 import moment from 'moment'
+import { notification, Modal } from 'antd'
+
+import MKEmitter from '@/utils/events.js'
 import Utils from './utils.js'
 
 export default class DataUtils {
   /**
-   * @description 鏁版嵁婧愬悕绉帮紝鐢ㄤ簬缁熶竴鏌ヨ
-   * @param {Object}   setting      鏁版嵁婧愯缃�
-   * @param {Array}    search       鎼滅储鏉′欢
-   * @param {String}   orderBy      鎺掑簭鏂瑰紡
-   * @param {Number}   pageIndex    椤电爜
-   * @param {Number}   pageSize     姣忛〉鏁伴噺
-   * @param {String}   BID          涓婄骇ID
+   * @description 鏁版嵁婧愮粺涓�鏌ヨ
    */
   static getQueryDataParams (setting, search = [], orderBy = '', pageIndex = 1, pageSize = 10, BID, id, year) {
     let param = null
@@ -49,6 +46,10 @@
       param.PageSize = pageSize
     } else if (setting.$re_year) {
       param.mk_year = year
+    }
+
+    if (setting.hasExtend) {
+      param.mk_time = setting.extendTime
     }
 
     if (setting.interType === 'inner') {
@@ -153,6 +154,9 @@
       { reg: /@typename@/ig, value: `'admin'`},
     )
 
+    if (setting.hasExtend) {
+      regoptions.push({ reg: /@mk_time@/ig, value: setting.extendTime })
+    }
     if (setting.$re_year) {
       regoptions.push({ reg: /@mk_year@/ig, value: year })
     }
@@ -442,6 +446,46 @@
 
     return param
   }
+
+  /**
+   * @description 鏁版嵁鑾峰彇鎴愬姛
+   */
+  static querySuccess (result) {
+    if (!result.message) return
+
+    if (result.ErrCode === 'Y') {
+      Modal.success({
+        title: result.message
+      })
+    } else if (result.ErrCode === 'S') {
+      notification.success({
+        top: 92,
+        message: result.message,
+        duration: 2
+      })
+    }
+  }
+
+  /**
+   * @description 鏁版嵁鑾峰彇澶辫触
+   */
+  static queryFail (result) {
+    if (!result.message && result.ErrCode !== 'version_up') return
+    
+    if (result.ErrCode === 'N') {
+      Modal.error({
+        title: result.message,
+      })
+    } else if (result.ErrCode === 'version_up') {
+      MKEmitter.emit('reloadTabs')
+    } else if (result.ErrCode !== '-2') {
+      notification.error({
+        top: 92,
+        message: result.message,
+        duration: 10
+      })
+    }
+  }
 }
 
 /**
diff --git a/src/utils/utils.js b/src/utils/utils.js
index a904374..be865dc 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -204,6 +204,13 @@
       values = window.GLOB.SearchBox.get(config.$searchId + 'cache')
     }
 
+    let supModule = ''
+    if (config.setting && config.setting.supModule) {
+      supModule = config.setting.supModule
+    } else if (config.wrap && config.wrap.supModule) {
+      supModule = config.wrap.supModule
+    }
+
     config.search = config.search.map(item => {
       item.hidden = item.Hide === 'true'
       item.required = !item.hidden && item.required === 'true'
@@ -234,12 +241,14 @@
           } else {
             item.$initval = item.initval
             item.$supId = config.$pageId
-            if (config.setting && config.setting.supModule) {
-              item.$supId = config.setting.supModule
+            if (supModule) {
+              item.$supId = supModule
 
               config.checkBid = true
-              config.setting.checkBid = true
               item.checkShift = true
+              if (config.setting) {
+                config.setting.checkBid = true
+              }
             }
 
             item.initval = ''
@@ -296,12 +305,14 @@
           } else {
             item.$initval = item.initval
             item.$supId = config.$pageId
-            if (config.setting && config.setting.supModule) {
-              item.$supId = config.setting.supModule
+            if (supModule) {
+              item.$supId = supModule
 
               config.checkBid = true
-              config.setting.checkBid = true
               item.checkShift = true
+              if (config.setting) {
+                config.setting.checkBid = true
+              }
             }
 
             item.initval = ''
@@ -393,10 +404,12 @@
           item.initType = ''
         }
       } else if ((item.type === 'select' || item.type === 'link') && item.resourceType === '1') {
-        if (/@BID@/ig.test(item.dataSource) && config.setting && config.setting.supModule) {
+        if (/@BID@/ig.test(item.dataSource) && supModule) {
           config.checkBid = true
-          config.setting.checkBid = true
           item.checkBid = true
+          if (config.setting) {
+            config.setting.checkBid = true
+          }
         }
         if (item.initval === '$first') {
           item.initval = ''
@@ -541,8 +554,8 @@
       } else if (item.type === 'range') {
         let val = item.value.split(',')
 
-        newsearches[item.key] = val[0] || -999999
-        newsearches[item.key + '1'] = val[1] || 999999
+        newsearches[item.key] = val[0] || -999999999
+        newsearches[item.key + '1'] = val[1] || 999999999
       } else if (item.type === 'dateweek') {
         let _startval = ''
         let _endval = ''
@@ -690,7 +703,7 @@
       } else if (item.type === 'range') {
         let val = item.value.split(',')
 
-        searchText.push('(' + item.key + ' >= ' + (val[0] || -999999) + ' AND ' + item.key + ' < ' + (val[1] || 999999) + ')')
+        searchText.push('(' + item.key + ' >= ' + (val[0] || -999999999) + ' AND ' + item.key + ' <= ' + (val[1] || 999999999) + ')')
       } else {
         searchText.push('(' + item.key + ' ' + item.match + ' \'' + item.value + '\')')
       }
@@ -766,9 +779,9 @@
 
         let copy = JSON.parse(JSON.stringify(item))
         copy.key = copy.key + '1'
-        copy.value = val[1] || 999999
+        copy.value = val[1] || 999999999
         
-        item.value = val[0] || -999999
+        item.value = val[0] || -999999999
 
         options.push(item)
         options.push(copy)
@@ -838,24 +851,6 @@
 
     let realurl = url.match(/^http/) || url.match(/^\/\//) ? url : window.GLOB.baseurl + url
     return realurl
-  }
-
-  /**
-   * @description 鑾峰彇浜戠鍥剧墖鐪熷疄璺緞
-   * @return {String}    url 鍥剧墖璺緞
-   */
-  static getcloudurl (url) {
-    if (!url) return ''
-    
-    let baseurl = ''
-    
-    if (window.GLOB.cloudServiceApi) {
-      baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
-    } else {
-      baseurl = window.GLOB.baseurl
-    }
-
-    return url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
   }
 
   /**
@@ -1132,6 +1127,13 @@
 
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      btn.columns.forEach((col) => {
+        if (/^Nvarchar/ig.test(col.type)) {
+          textFields.push(col.Column)
+        }
+      })
+
       btn.uniques.forEach(unique => {
         if (unique.status === 'false' || !unique.verifyType) return
 
@@ -1140,6 +1142,14 @@
         let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
 
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
+
         if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
@@ -1147,7 +1157,7 @@
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
       Set @tbid=''
-      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ) a group by ${unique.field} having sum(n)>1
+      Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${unique.field} from #${sheet} ${_where}) a group by ${unique.field} having sum(n)>1
       
       If @tbid!=''
       Begin
@@ -1156,7 +1166,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${database}${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${database}${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
@@ -1411,7 +1421,7 @@
 
     sql = `
       /* 绯荤粺鐢熸垚 */
-      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(50) )
+      create table #${sheet} (${declarefields.join(',')},jskey nvarchar(50),data_type nvarchar(50),BID nvarchar(256))
       Declare @UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100),@ErrorCode nvarchar(50),@retmsg nvarchar(4000),@tbid Nvarchar(512)
       
       Select  @ErrorCode='', @retmsg='', @UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
@@ -2121,7 +2131,13 @@
     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
 
     if (verify.flowType === 'start') {
       target = flow.cells.filter(cell => cell.mknode === 'start')[0]
@@ -2145,25 +2161,18 @@
         if (verify.flowType === 'reject') {
           line = lines.filter(cell => cell.mkdata.flowType === 'reject' || cell.mknode === 'startEdge')[0]
         } else {
-          let endEdge = null
-          lines = lines.filter(cell => {
-            if (cell.mknode === 'endEdge') {
-              endEdge = cell
-              return false
-            }
-
-            return cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge'
-          })
+          lines = lines.filter(cell => cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge')
 
           if (lines.length === 0) {
-            if (!endEdge) {
-              error = '鏃犲彲鎵ц鐨勬祦绋嬪垎鏀�'
-            } else {
-              line = endEdge
-            }
+            error = '鏃犲彲鎵ц鐨勬祦绋嬪垎鏀�'
           } else {
             let branchKey = verify.flowBranch ? 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') {
@@ -2171,18 +2180,31 @@
                 }
               })
               if (!error) {
-                line = lines[0]
+                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 = '琛屼俊鎭腑鏃犳祦绋嬫帶鍒跺瓧娈点��'
+              error = '淇℃伅涓棤娴佺▼鎺у埗瀛楁銆�'
             } else {
-              if (endEdge) {
-                line = endEdge
-              }
-
-              let equalLine = null
-              let gtOrLtLine = []
-              let unEqualLine = null
+              let _def_lines = []
+              let _equ_lines = []
+              let _unequ_lines = []
+              let _or_lines = []
               let branchVal = _data[branchKey]
 
               if (branchVal && typeof(branchVal) === 'string' && !isNaN(branchVal)) {
@@ -2191,45 +2213,58 @@
 
               lines.forEach(item => {
                 if (item.mkdata.execCondition !== 'open') {
-                  line = item
+                  _def_lines.push(item)
                 } else {
                   if (item.mkdata.match === '=') {
                     if (item.mkdata.matchVal === branchVal + '') {
-                      equalLine = item
+                      _equ_lines.push(item)
                     }
                   } else if (item.mkdata.match === '!=') {
                     if (item.mkdata.matchVal !== branchVal + '') {
-                      unEqualLine = item
+                      _unequ_lines.push(item)
                     }
                   } else {
                     if (item.mkdata.match === '<') {
                       if (item.mkdata.matchVal < branchVal) {
-                        gtOrLtLine.push({...item, dist: Math.abs(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) {
-                        gtOrLtLine.push({...item, dist: Math.abs(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) {
-                        gtOrLtLine.push({...item, dist: Math.abs(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) {
-                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                        _or_lines.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
                       }
                     }
                   }
                 }
               })
 
-              if (equalLine) {
-                line = equalLine
-              } else if (gtOrLtLine.length > 0) {
-                gtOrLtLine.sort((a, b) => a.dist - b.dist)
-                line = gtOrLtLine[0]
-              } else if (unEqualLine) {
-                line = unEqualLine
+              _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]
               }
             }
           }
@@ -2242,7 +2277,36 @@
         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 = '宸ヤ綔娴佷腑鏃犲搴旀祦绋�'
       }
@@ -2250,27 +2314,140 @@
       error = '琛屼俊鎭腑鏃犲伐浣滄祦鍙傛暟'
     }
 
-    if (verify.flowSql === 'true' && target) {
+    if (error) {
+      status = 0
+      statusName = '寮傚父'
+
+      _sql += `
+      /* 宸ヤ綔娴佸紓甯竤ql */
+      select @ErrorCode='E',@retmsg='${error}' goto aaa
+      `
+    } else if (verify.flowSql === 'true') {
       if (verify.flowType === 'start') {
         _sql += `
       /* 宸ヤ綔娴侀粯璁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,upid)
-      select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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 if (line.approvalMethod === 'countersign' && node.checkIds.length > 1) {
+        let label = ''
+        let field = ''
+        let mark = line.mark || '宸插鏍�'
+        let _declare = []
+        let _select = []
+        let _select2 = []
+        let _where = []
+        let fields = ['statuscharone', 'statuschartwo', 'statuscharthree', 'statuscharfour', 'statuscharfive']
+        node.checkUsers.forEach((user, index) => {
+          if (user.worker_id === userid) {
+            field = fields[index]
+            label = `'${user.parentNames[2] || ''}${user.workername || ''}${mark}'`
+          } else {
+            _declare.push(`@works_flow_${fields[index]} nvarchar(50)`)
+            _select.push(`@works_flow_${fields[index]}=''`)
+            _select2.push(`@works_flow_${fields[index]}=${fields[index]}`)
+            _where.push(`@works_flow_${fields[index]}!=''`)
+          }
+        })
+        _declare = _declare.join(',')
+        _select = _select.join(',')
+        _select2 = _select2.join(',')
+        _where = _where.join(' and ')
+
+        _sql += `
+      /* 宸ヤ綔娴侀粯璁ql */
+      declare ${_declare},@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 ${_select},@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 ${_select2},@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 ${_where}
+      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
       `
       } else {
         _sql += `
       /* 宸ヤ綔娴侀粯璁ql */
-      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(),modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
+      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
+
+          select @retmsg='椤甸潰鏁版嵁宸叉洿鏂帮紝鎴栨病鏈夊綋鍓嶅崟鎹殑瀹℃壒鏉冮檺'
+            goto aaa 
+      end
+      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,upid)
-      select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@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${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 : ''}
+      
+      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
+
+      ${line.mknode === 'startEdge' ? `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'` : ''}
+
       if @check_userids@ != ''
       begin
-            delete s_my_works_flow_role where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
             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)
@@ -2278,7 +2455,8 @@
       end
       if @notice_userids@ != ''
       begin
-            delete n
+            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
@@ -2287,33 +2465,16 @@
       end
       `
       }
-    } else if (verify.flowSql === 'true') {
-      status = 0
-      statusName = '寮傚父'
-
-      _sql += `
-      /* 宸ヤ綔娴佸紓甯竤ql */
-      select @ErrorCode='E',@retmsg='${error || '宸ヤ綔娴佹墽琛屽紓甯�'}' goto aaa
-      `
     }
 
-    if (verify.flowType !== 'start') {
-      if (line) {
-        let checkIds = []
-        let noticeIds = []
-        line.mkdata.members && line.mkdata.members.forEach(item => {
-          checkIds.push(item.worker_id)
-        })
-        line.mkdata.copys && line.mkdata.copys.forEach(item => {
-          noticeIds.push(item.worker_id)
-        })
-        _sql = _sql.replace(/@check_userids@/ig, `'${checkIds.join(',')}'`)
-        _sql = _sql.replace(/@notice_userids@/ig, `'${noticeIds.join(',')}'`)
-      } else {
-        _sql = _sql.replace(/@check_userids@/ig, `''`)
-        _sql = _sql.replace(/@notice_userids@/ig, `''`)
-      }
+    if (_backCustomScript) {
+      _sql += _backCustomScript
     }
+
+    _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(/@start_type@/ig, `'寮�濮�'`)
     _sql = _sql.replace(/@check_type@/ig, verify.flowType === 'reject' ? `'椹冲洖'` : `'瀹℃牳'`)
@@ -2321,9 +2482,10 @@
 
     _sql = _sql.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
     _sql = _sql.replace(/@works_flow_name@/ig, `'${flow.flow_name}'`)
+
     if (target) {
       let label = target.attrs && target.attrs.text && target.attrs.text.text ? target.attrs.text.text : ''
-      let msg = {...target.mkdata, label: label, id: target.id}
+      let msg = {...target.mkdata, label: label, id: target.id, checkIds, checkUsers}
       _sql = _sql.replace(/@works_flow_param@/ig, `'${window.btoa(window.encodeURIComponent(JSON.stringify(msg)))}'`)
     } else {
       _sql = _sql.replace(/@works_flow_param@/ig, `''`)
@@ -2332,10 +2494,8 @@
     _sql = _sql.replace(/@status@/ig, `'${status}'`)
     _sql = _sql.replace(/@statusname@/ig, `'${statusName}'`)
     _sql = _sql.replace(/@work_group@/ig, `'${sessionStorage.getItem('work_group') || ''}'`)
-    _sql = _sql.replace(/@work_grade@/ig, `'${sessionStorage.getItem('work_grade') || 0}'`)
-  }
-
-  if (_backCustomScript) {
+    _sql = _sql.replace(/@work_grade@/ig, `'${work_grade}'`)
+  } else if (_backCustomScript) {
     _sql += _backCustomScript
   }
 
diff --git a/src/views/appcheck/header/index.jsx b/src/views/appcheck/header/index.jsx
index 96bba6d..a5de4ee 100644
--- a/src/views/appcheck/header/index.jsx
+++ b/src/views/appcheck/header/index.jsx
@@ -7,13 +7,16 @@
 class AppManageHeader extends Component {
   state = {
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
-    userName: sessionStorage.getItem('CloudUserName')
+    userName: sessionStorage.getItem('CloudUserName'),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   render () {
+    const { logo } = this.state
+
     return (
       <header className="app-manage-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="title">
           搴旂敤绠$悊
         </div>
diff --git a/src/views/appmanage/header/index.jsx b/src/views/appmanage/header/index.jsx
index 96bba6d..a5de4ee 100644
--- a/src/views/appmanage/header/index.jsx
+++ b/src/views/appmanage/header/index.jsx
@@ -7,13 +7,16 @@
 class AppManageHeader extends Component {
   state = {
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
-    userName: sessionStorage.getItem('CloudUserName')
+    userName: sessionStorage.getItem('CloudUserName'),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   render () {
+    const { logo } = this.state
+
     return (
       <header className="app-manage-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="title">
           搴旂敤绠$悊
         </div>
diff --git a/src/views/basedesign/updateFormTab/index.jsx b/src/views/basedesign/updateFormTab/index.jsx
index 5fb70ae..d17db4b 100644
--- a/src/views/basedesign/updateFormTab/index.jsx
+++ b/src/views/basedesign/updateFormTab/index.jsx
@@ -1195,14 +1195,10 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.execSuccess === 'maingrid') {
-        _btn.execSuccess = 'mainline'
       }
 
       if (_btn.execError === 'equaltab') {
         _btn.execError = 'grid'
-      } else if (_btn.execError === 'maingrid') {
-        _btn.execError = 'mainline'
       }
 
       if (_btn.popClose === 'equaltab') {
@@ -1212,8 +1208,6 @@
         if (newCon.equalTab && oldtabs && oldtabs[newCon.equalTab]) {
           _btn.syncComponent.push(oldtabs[newCon.equalTab])
         }
-      } else if (_btn.popClose === 'maingrid') {
-        _btn.popClose = 'mainline'
       }
 
       if (_btn.OpenType === 'pop' || (_btn.OpenType === 'funcbutton' && _btn.funcType === 'print' && _btn.execMode === 'pop')) {
diff --git a/src/views/billprint/index.jsx b/src/views/billprint/index.jsx
index 85f4b7e..416c51d 100644
--- a/src/views/billprint/index.jsx
+++ b/src/views/billprint/index.jsx
@@ -1,6 +1,6 @@
 import React, { Component } from 'react'
 import { is, fromJS } from 'immutable'
-import { Col, Row, Spin, notification, Button } from 'antd'
+import { Col, Row, Spin, notification, Button, Modal } from 'antd'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -47,6 +47,8 @@
     auto: true,
     ismob: /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent)
   }
+
+  reloading = false
 
   UNSAFE_componentWillMount() {
     const { params } = this.props.match
@@ -367,7 +369,9 @@
             let getColumns = (cols) => {
               return cols.filter(item => {
                 if (item.Hide === 'true') return false
-                  
+
+                item.IsSort = 'false'
+
                 if (item.type === 'number') {
                   if (typeof(item.decimal) === 'number') {
                     item.round = Math.pow(10, item.decimal)
@@ -629,6 +633,9 @@
 
     if (cell.marks && cell.marks.length === 0) {
       cell.marks = null
+    }
+    if (cell.anchors && cell.anchors.length === 0) {
+      cell.anchors = null
     }
     
     if (['text', 'number', 'formula'].includes(cell.eleType)) {
@@ -912,11 +919,15 @@
             if (item.func === 'sPC_Get_structured_data' && /灏嗘埅鏂瓧绗︿覆鎴栦簩杩涘埗鏁版嵁/ig.test(res.message)) {
               res.message = res.message + '璇锋鏌ュ瓧娈甸泦'
             }
-            notification.warning({
-              top: 92,
-              message: res.message,
-              duration: 5
-            })
+            if (res.ErrCode === 'version_up') {
+              this.reloadTabs()
+            } else {
+              notification.warning({
+                top: 92,
+                message: res.message,
+                duration: 5
+              })
+            }
             resolve(false)
           } else {
             res.componentId = componentId
@@ -1076,6 +1087,20 @@
     })
   }
 
+  reloadTabs = () => {
+    if (this.reloading) return
+
+    this.reloading = true
+
+    Api.getAppVersion(true).then(() => {
+      window.location.reload()
+    }, (message) => {
+      Modal.error({
+        title: message || '绯荤粺閰嶇疆鏇存柊澶辫触锛�',
+      })
+    })
+  }
+
   canvasToImage(canvas) {
     let image = new Image()
     image.src = canvas.toDataURL('image/jpg')
diff --git a/src/views/design/header/index.jsx b/src/views/design/header/index.jsx
index 009135a..1184437 100644
--- a/src/views/design/header/index.jsx
+++ b/src/views/design/header/index.jsx
@@ -23,6 +23,7 @@
     menulist: null, // 涓�绾ц彍鍗�
     userName: sessionStorage.getItem('CloudUserName'),
     avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo,
     visible: false,
     loading: false
   }
@@ -409,11 +410,11 @@
 
   render () {
     const { mainMenu, editLevel } = this.props
-    const { menulist, visible, loading } = this.state
+    const { menulist, visible, loading, logo } = this.state
 
     return (
       <header className={'sys-header-container ant-menu-dark ' + (['level2', 'level3'].includes(editLevel) ? 'mask' : '')} id="main-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="header-collapse">
           <MenuFoldOutlined/>
         </div>
diff --git a/src/views/design/sidemenu/thdmenuform/index.jsx b/src/views/design/sidemenu/thdmenuform/index.jsx
index cb8f0da..08ba9d6 100644
--- a/src/views/design/sidemenu/thdmenuform/index.jsx
+++ b/src/views/design/sidemenu/thdmenuform/index.jsx
@@ -147,7 +147,7 @@
           </Col>
           {menu.Template === 'NewPage' ? <Col span={22}>
             <Form.Item label={
-              <Tooltip overlayStyle={{minWidth: 500}} placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>浣跨敤鍚屼竴鍗曠偣绯荤粺涓嬬殑鍏朵粬涓氬姟绯荤粺锛岄摼鎺ユ牸寮忎负锛歨ttp://<span style={{color: 'orange'}}>******</span>/admin/index.html#/iframe/<span style={{color: 'orange'}}>menuId</span>/<span style={{color: 'orange'}}>loginuid</span>/<span style={{color: 'orange'}}>BID</span>銆傛敞锛�******涓哄煙鍚�+铏氭嫙鐩綍锛沵enuId涓鸿彍鍗旾D锛沴oginuid涓虹櫥褰曚俊鎭紙浣跨敤@loginuid@鏃惰嚜鍔ㄦ浛鎹负褰撳墠绯荤粺鐨刲oginuid锛夛紱BID鏄悜鑿滃崟涓殑浼犲弬锛屽彲涓虹┖銆�</div>}><QuestionCircleOutlined className="mk-form-tip" />閾炬帴鍦板潃</Tooltip>
+              <Tooltip overlayStyle={{minWidth: 500}} placement="topLeft" title={<div onClick={(e) => e.stopPropagation()}>浣跨敤鍚屼竴鍗曠偣绯荤粺涓嬬殑鍏朵粬涓氬姟绯荤粺锛岄摼鎺ユ牸寮忎负锛歨ttp://<span style={{color: 'orange'}}>******</span>/admin/index.html#/iframe/<span style={{color: 'orange'}}>menuId</span>/<span style={{color: 'orange'}}>@loginuid@</span>/<span style={{color: 'orange'}}>BID</span>銆傛敞锛�******涓哄煙鍚�+铏氭嫙鐩綍锛沵enuId涓鸿彍鍗旾D锛汙loginuid@涓虹櫥褰曚俊鎭紙绯荤粺鑷姩鏇挎崲锛夛紱BID鏄悜鑿滃崟涓殑浼犲弬锛屽彲涓虹┖銆�</div>}><QuestionCircleOutlined className="mk-form-tip" />閾炬帴鍦板潃</Tooltip>
             }>
               {getFieldDecorator('url', {
                 initialValue: menu.url || '',
diff --git a/src/views/interface/header/index.jsx b/src/views/interface/header/index.jsx
index 903325e..a3944b8 100644
--- a/src/views/interface/header/index.jsx
+++ b/src/views/interface/header/index.jsx
@@ -9,6 +9,7 @@
   state = {
     userName: sessionStorage.getItem('CloudUserName'),
     avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   UNSAFE_componentWillMount() {}
@@ -18,10 +19,11 @@
   }
 
   render () {
+    const { logo } = this.state
 
     return (
       <header className="interface-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="title">鎺ュ彛璋冭瘯</div>
         <div className="header-setting">
           <span className="close" onClick={this.close}>鍏抽棴</span>
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index fca05c8..75dcf09 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -60,17 +60,6 @@
     sessionStorage.setItem('lang', lang)
   }
 
-  changelang (item) {
-    // 鍒囨崲璇█
-    // this.setState({
-    //   dict: item === 'zh-CN' ? zhCN : enUS
-    // })
-    localStorage.setItem(_href + 'lang', item !== 'en-US' ? 'zh-CN' : 'en-US')
-    sessionStorage.setItem('lang', item !== 'en-US' ? 'zh-CN' : 'en-US')
-
-    window.location.reload()
-  }
-
   handleSubmit = () => {
     this.loginformRef.handleConfirm().then(res => {
       this.setState({
@@ -408,6 +397,7 @@
     authCode = authCode ? authCode.split(',') : []
     let index = authCode.findIndex(key => key === _s)
     let license = false
+    let appkey = window.GLOB.localkey || window.GLOB.appkey
 
     if (window.GLOB.licenseKey) {
       if (window.GLOB.licenseKey.length !== 20) {
@@ -416,7 +406,7 @@
           okText: '鐭ラ亾浜�'
         })
       } else {
-        let key = md5(window.GLOB.appId + 'minke_software' + window.GLOB.appkey).toUpperCase().substr(-6)
+        let key = md5(window.GLOB.appId + 'minke_software' + appkey).toUpperCase().substr(-6)
   
         let key1 = window.GLOB.licenseKey.substring(0, 6)
         let key2 = window.GLOB.licenseKey.substring(6, 14)
@@ -424,7 +414,7 @@
         let key4 = md5(key1 + key2).toUpperCase().substr(-6)
   
         if (key === key1 && key3 === key4) {
-          let last = window.GLOB.appkey[window.GLOB.appkey.length - 1]
+          let last = appkey[appkey.length - 1]
           let offset = 0
           let keys = {}
       
@@ -497,7 +487,7 @@
         func: _func,
         AppID: window.GLOB.appId,
         TimeStamp: timeStamp,
-        appkey: window.GLOB.appkey,
+        appkey: appkey,
         SessionUid: localStorage.getItem('SessionUid') || '',
         userid: _id,
         LoginUID: _id,
@@ -627,7 +617,8 @@
         let _param = {
           func: 's_Get_style',
           TypeCharOne: 'PC',
-          LText: `select '${window.GLOB.appkey}'`,
+          LText: `select '${appkey}'`,
+          appkey: appkey
         }
 
         _param.userid = result.UserID
@@ -685,7 +676,7 @@
             }
 
             if ([10, 20, 30, 40, 50, 60, 70, 80, 90, 100].includes(res.member_level)) {
-              systemMsg.Member_Level = md5('mksoft' + window.GLOB.appkey + res.member_level)
+              systemMsg.Member_Level = md5('mksoft' + appkey + res.member_level)
               if (!window.GLOB.memberLevel) {
                 Object.defineProperty(window.GLOB, 'memberLevel', {
                   writable: false,
@@ -999,7 +990,6 @@
             lang={this.state.selectedlang}
             langList={this.state.langList}
             isDisabled={this.state.isDisabled}
-            changelang={(value) => this.changelang(value)}
             handleSubmit={() => this.handleSubmit()}
             authLogin={this.authLogin}
             wrappedComponentRef={(inst) => this.loginformRef = inst}
diff --git a/src/views/login/index.scss b/src/views/login/index.scss
index ac68645..736416c 100644
--- a/src/views/login/index.scss
+++ b/src/views/login/index.scss
@@ -303,6 +303,12 @@
         }
       }
     }
+
+    .qr-wrap + img {
+      width: 24px;
+      margin-right: 5px;
+      vertical-align: middle;
+    }
   }
 }
 .mk-user-option {
diff --git a/src/views/login/loginform.jsx b/src/views/login/loginform.jsx
index 03c6521..8939de7 100644
--- a/src/views/login/loginform.jsx
+++ b/src/views/login/loginform.jsx
@@ -14,7 +14,6 @@
 class LoginTabForm extends Component {
   static propTpyes = {
     isDisabled: PropTypes.bool,
-    changelang: PropTypes.func,
     handleSubmit: PropTypes.func,
     dict: PropTypes.object,
     auth: PropTypes.bool,
@@ -94,8 +93,12 @@
     })
   }
 
-  changelang = (item) => {
-    this.props.changelang(item)
+  changelang = (val) => {
+    const _href = window.location.href.split('#')[0]
+    localStorage.setItem(_href + 'lang', val)
+    sessionStorage.setItem('lang', val)
+
+    window.location.reload()
   }
 
   handleSubmit = e => {
@@ -354,7 +357,7 @@
               initialValue: this.props.lang,
             })(
               <Select
-                onChange={(value) => {this.props.changelang(value)}}
+                onChange={(value) => {this.changelang(value)}}
                 getPopupContainer={() => document.getElementById('login-form')}
               >
                 {langList.map((item, index) => {
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index 7d3ece5..ad11d1f 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -654,7 +654,7 @@
         
         if (item.action && item.action.length > 0) {
           item.action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
             buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
             _sort++
           })
@@ -669,13 +669,13 @@
           item.subcards.forEach(card => {
             card.elements && card.elements.forEach(cell => {
               if (cell.eleType !== 'button') return
-              if (cell.hidden === 'true') return
+              if (cell.hidden === 'true' || cell.permission === 'false') return
               buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
               _sort++
             })
             card.backElements && card.backElements.forEach(cell => {
               if (cell.eleType !== 'button') return
-              if (cell.hidden === 'true') return
+              if (cell.hidden === 'true' || cell.permission === 'false') return
               buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
               _sort++
             })
@@ -683,7 +683,7 @@
         } else if (item.type === 'balcony') {
           item.elements && item.elements.forEach(cell => {
             if (cell.eleType !== 'button') return
-            if (cell.hidden === 'true') return
+            if (cell.hidden === 'true' || cell.permission === 'false') return
             buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
             _sort++
           })
@@ -694,7 +694,7 @@
                 loopCol(col.subcols)
               } else if (col.type === 'custom') {
                 col.elements.forEach(cell => {
-                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
                   buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
                   _sort++
                 })
@@ -799,6 +799,11 @@
 
       let tbs = []
       let btns = this.getMenuMessage(config, tbs)
+
+      if (config.permission === 'false') {
+        btns = []
+      }
+
       let arr = []
       tbs = tbs.filter(tb => {
         let _tb = tb.toLowerCase()
@@ -828,6 +833,7 @@
       }
 
       let interfaces = getFuncsAndInters(config)
+      let urlFields = config.urlFields ? config.urlFields.join(',') : ''
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -839,7 +845,7 @@
         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}),
+        PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, urlFields}),
         open_edition: config.open_edition,
         LText: '',
         LTexttb: '',
@@ -882,10 +888,21 @@
   
             Api.fileuploadbase64(param).then(result => {
               if (result.status) {
+                let url = result.Images
+                let baseurl = ''
+    
+                if (window.GLOB.cloudServiceApi) {
+                  baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
+                } else {
+                  baseurl = window.GLOB.baseurl
+                }
+
+                url = url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
+
                 Api.getCloudConfig({
                   func: 's_PrintTemplateMSub',
                   ID: config.uuid,
-                  Images: Utils.getcloudurl(result.Images),
+                  Images: url,
                   Remark: '',
                   temp_type: 'billprint',
                 }).then(response => {
@@ -1154,6 +1171,7 @@
   updateLogConfig = (config) => {
     config.fstMenuId = this.state.config.fstMenuId || config.fstMenuId || ''
     config.parentId = this.state.config.parentId || config.parentId || ''
+    config.open_edition = this.state.config.open_edition || ''
     
     this.setState({
       config: null
diff --git a/src/views/menudesign/popview/index.jsx b/src/views/menudesign/popview/index.jsx
index 1cf34b5..394ca23 100644
--- a/src/views/menudesign/popview/index.jsx
+++ b/src/views/menudesign/popview/index.jsx
@@ -72,13 +72,13 @@
     const { oriConfig, config } = this.state
 
     if (!is(fromJS(oriConfig), fromJS(config))) {
-      const _this = this
+      const that = this
 
       confirm({
         title: '閰嶇疆宸蹭慨鏀癸紝鏀惧純淇濆瓨鍚楋紵',
         content: '',
         onOk() {
-          _this.props.cancel()
+          that.props.cancel()
         },
         onCancel() {}
       })
diff --git a/src/views/mkiframe/index.jsx b/src/views/mkiframe/index.jsx
index 2547d9d..b6e9761 100644
--- a/src/views/mkiframe/index.jsx
+++ b/src/views/mkiframe/index.jsx
@@ -19,6 +19,8 @@
     type: 'CustomPage'
   }
 
+  reloading = false
+
   UNSAFE_componentWillMount() {
     const { params, path } = this.props.match
     const { menuId, loginUid, bid } = params
@@ -112,6 +114,10 @@
     MKEmitter.addListener('modifyTabs', this.modifyTabs)
     MKEmitter.addListener('closeTabView', this.closeTabView)
 
+    if (window.GLOB.forcedUpdate) {
+      MKEmitter.addListener('reloadTabs', this.reloadTabs)
+    }
+
     if (window.GLOB.sysType !== 'cloud') {
       Object.defineProperty(window, 'debugger', {
         configurable: true,
@@ -152,7 +158,24 @@
       return
     }
     MKEmitter.removeListener('modifyTabs', this.modifyTabs)
+    MKEmitter.removeListener('reloadTabs', this.reloadTabs)
     MKEmitter.removeListener('closeTabView', this.closeTabView)
+  }
+
+  reloadTabs = () => {
+    if (this.reloading) return
+
+    this.reloading = true
+
+    Api.getAppVersion(true).then(() => {
+      window.location.reload()
+    }, (message) => {
+      notification.error({
+        top: 92,
+        message: message || '绯荤粺閰嶇疆鏇存柊澶辫触锛�',
+        duration: 10
+      })
+    })
   }
 
   modifyTabs = (tab) => {
@@ -183,7 +206,10 @@
     let historys = sessionStorage.getItem('page_historys')
     historys = historys ? JSON.parse(historys) : []
 
-    if (historys.length === 0) return
+    if (historys.length === 0) {
+      window.close()
+      return
+    }
 
     let tab = historys.shift()
 
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 575cb43..b713e00 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -1039,7 +1039,7 @@
           return
         } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
           item.action && item.action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
 
             m.children.push({
               key: btn.uuid,
@@ -1048,7 +1048,7 @@
           })
           item.subcards.forEach(card => {
             card.elements && card.elements.forEach(cell => {
-              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
               m.children.push({
                 key: cell.uuid,
@@ -1059,7 +1059,7 @@
             if (item.subtype !== 'dualdatacard') return
             
             card.backElements && card.backElements.forEach(cell => {
-              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
               m.children.push({
                 key: cell.uuid,
@@ -1069,7 +1069,7 @@
           })
         } else if (item.type === 'balcony') {
           item.elements && item.elements.forEach(cell => {
-            if (cell.eleType !== 'button' || cell.hidden === 'true') return
+            if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
             m.children.push({
               key: cell.uuid,
@@ -1098,7 +1098,7 @@
           }
         } else if (item.type === 'table') {
           item.action && item.action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
 
             m.children.push({
               key: btn.uuid,
@@ -1111,7 +1111,7 @@
                 loopCol(col.subcols)
               } else if (col.type === 'custom') {
                 col.elements.forEach(cell => {
-                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
                   m.children.push({
                     key: cell.uuid,
                     title: cell.label,
@@ -2030,6 +2030,8 @@
   }
 
   updateLogConfig = (config) => {
+    config.open_edition = this.state.config.open_edition || ''
+    
     this.setState({
       config: null
     }, () => {
diff --git a/src/views/mobdesign/popview/index.jsx b/src/views/mobdesign/popview/index.jsx
index bfd1bf1..15edee3 100644
--- a/src/views/mobdesign/popview/index.jsx
+++ b/src/views/mobdesign/popview/index.jsx
@@ -74,13 +74,13 @@
     const { oriConfig, config } = this.state
 
     if (!is(fromJS(oriConfig), fromJS(config))) {
-      const _this = this
+      const that = this
 
       confirm({
         title: '閰嶇疆宸蹭慨鏀癸紝鏀惧純淇濆瓨鍚楋紵',
         content: '',
         onOk() {
-          _this.props.cancel()
+          that.props.cancel()
         },
         onCancel() {}
       })
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index 4efe859..63ef5fb 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -877,7 +877,7 @@
           return
         } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
           item.action && item.action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
 
             m.children.push({
               key: btn.uuid,
@@ -886,7 +886,7 @@
           })
           item.subcards.forEach(card => {
             card.elements && card.elements.forEach(cell => {
-              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
               m.children.push({
                 key: cell.uuid,
@@ -895,7 +895,7 @@
             })
 
             card.backElements && card.backElements.forEach(cell => {
-              if (cell.eleType !== 'button' || cell.hidden === 'true') return
+              if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
               m.children.push({
                 key: cell.uuid,
@@ -905,7 +905,7 @@
           })
         } else if (item.type === 'balcony') {
           item.elements && item.elements.forEach(cell => {
-            if (cell.eleType !== 'button' || cell.hidden === 'true') return
+            if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
 
             m.children.push({
               key: cell.uuid,
@@ -923,7 +923,7 @@
           }
         } else if (item.type === 'table') {
           item.action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
 
             m.children.push({
               key: btn.uuid,
@@ -936,7 +936,7 @@
                 loopCol(col.subcols)
               } else if (col.type === 'custom') {
                 col.elements.forEach(cell => {
-                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
                   m.children.push({
                     key: cell.uuid,
                     title: cell.label,
@@ -1679,6 +1679,8 @@
   }
 
   updateLogConfig = (config) => {
+    config.open_edition = this.state.config.open_edition || ''
+    
     this.setState({
       config: null
     }, () => {
diff --git a/src/views/printTemplate/index.jsx b/src/views/printTemplate/index.jsx
index dcb5d22..8f72e0c 100644
--- a/src/views/printTemplate/index.jsx
+++ b/src/views/printTemplate/index.jsx
@@ -831,7 +831,18 @@
         
         Api.fileuploadbase64(param).then(result => { // 鍥剧墖涓婁紶锛屽苟鑾峰彇鍥剧墖璺緞
           if (result.status) {
-            resolve(Utils.getcloudurl(result.Images))
+            let url = result.Images
+            let baseurl = ''
+
+            if (window.GLOB.cloudServiceApi) {
+              baseurl = window.GLOB.cloudServiceApi.replace(/webapi(.*)$/, '')
+            } else {
+              baseurl = window.GLOB.baseurl
+            }
+
+            url = url.match(/^http/) || url.match(/^\/\//) ? url : baseurl + url
+
+            resolve(url)
           } else {
             notification.warning({
               top: 92,
diff --git a/src/views/rolemanage/header/index.jsx b/src/views/rolemanage/header/index.jsx
index d49edb8..6fd53ce 100644
--- a/src/views/rolemanage/header/index.jsx
+++ b/src/views/rolemanage/header/index.jsx
@@ -7,14 +7,17 @@
 class AppManageHeader extends Component {
   state = {
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
-    userName: sessionStorage.getItem('CloudUserName')
+    userName: sessionStorage.getItem('CloudUserName'),
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   render () {
     const { app } = this.props
+    const { logo } = this.state
+
     return (
       <header className="app-manage-header-container">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="title">
           {`${app.remark} ${app.typename}`}
         </div>
diff --git a/src/views/systemfunc/header/index.jsx b/src/views/systemfunc/header/index.jsx
index c146a84..03f2dfc 100644
--- a/src/views/systemfunc/header/index.jsx
+++ b/src/views/systemfunc/header/index.jsx
@@ -8,14 +8,11 @@
   state = {
     userName: sessionStorage.getItem('CloudUserName'),
     avatar: sessionStorage.getItem('CloudAvatar') || avatar,
+    logo: sessionStorage.getItem('CloudLogo') || MainLogo
   }
 
   exitManage = () => {
     window.close()
-  }
-
-  UNSAFE_componentWillMount () {
-
   }
 
   /**
@@ -28,9 +25,11 @@
   }
 
   render () {
+    const { logo } = this.state
+
     return (
       <header className="sys-header-container ant-menu-dark">
-        <div className="header-logo"><img src={MainLogo} alt=""/></div>
+        <div className="header-logo"><img src={logo} alt=""/></div>
         <div className="title">HS</div>
         <div className="header-setting">
           <img src={this.state.avatar} alt=""/>
diff --git a/src/views/systemfunc/sidemenu/index.jsx b/src/views/systemfunc/sidemenu/index.jsx
index 53dc77f..a11e157 100644
--- a/src/views/systemfunc/sidemenu/index.jsx
+++ b/src/views/systemfunc/sidemenu/index.jsx
@@ -66,7 +66,7 @@
         if (menu) {
           menu = fromJS(menu).toJS()
           menu.param = {}
-          menu.param.$searchkey = 'PrintTempNO'
+          menu.param.$searchkey = 'printtempno'
           menu.param.$searchval = temp
           setTimeout(() => {
             MKEmitter.emit('modifyTabs', menu)
@@ -77,7 +77,7 @@
         if (menu) {
           menu = fromJS(menu).toJS()
           menu.param = {}
-          menu.param.$searchkey = 'PrintTempNO'
+          menu.param.$searchkey = 'printtempno'
           menu.param.$searchval = tabTemp
           setTimeout(() => {
             MKEmitter.emit('modifyTabs', menu)
diff --git a/src/views/tabledesign/index.jsx b/src/views/tabledesign/index.jsx
index 7d16779..3880a3d 100644
--- a/src/views/tabledesign/index.jsx
+++ b/src/views/tabledesign/index.jsx
@@ -459,7 +459,7 @@
           let _s = 1
 
           tab.components[0].action.forEach(btn => {
-            if (btn.hidden === 'true') return
+            if (btn.hidden === 'true' || btn.permission === 'false') return
 
             buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
             _s++
@@ -471,7 +471,7 @@
                 loopCol(col.subcols)
               } else if (col.type === 'custom') {
                 col.elements.forEach(cell => {
-                  if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                  if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
                   buttons.push(`select '${cell.uuid}' as menuid, '${cell.label}' as menuname, '${_s * 10}' as Sort, '${tab.components[0].uuid}' as parentid, 60 as Type`)
                   _s++
                 })
@@ -486,7 +486,7 @@
           tbs.push(...item.$tables)
         }
         item.action.forEach(btn => {
-          if (btn.hidden === 'true') return
+          if (btn.hidden === 'true' || btn.permission === 'false') return
 
           buttons.push(`select '${btn.uuid}' as menuid, '${btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
           _sort++
@@ -498,7 +498,7 @@
               loopCol(col.subcols)
             } else if (col.type === 'custom') {
               col.elements.forEach(cell => {
-                if (cell.eleType !== 'button' || cell.hidden === 'true') return
+                if (cell.eleType !== 'button' || cell.hidden === 'true' || cell.permission === 'false') return
                 buttons.push(`select '${cell.uuid}' as menuid,  '${cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
                 _sort++
               })
@@ -581,6 +581,7 @@
       }
 
       let interfaces = getFuncsAndInters(config)
+      let urlFields = config.urlFields ? config.urlFields.join(',') : ''
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -592,7 +593,7 @@
         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}),
+        PageParam: JSON.stringify({Template: 'BaseTable', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false', menuColor: config.menuColor || '', interfaces, urlFields}),
         open_edition: config.open_edition,
         LText: '',
         LTexttb: '',
@@ -826,6 +827,7 @@
   updateLogConfig = (config) => {
     config.fstMenuId = this.state.config.fstMenuId || config.fstMenuId || ''
     config.parentId = this.state.config.parentId || config.parentId || ''
+    config.open_edition = this.state.config.open_edition || ''
 
     this.setState({
       config: null
@@ -892,6 +894,13 @@
               <div className={'menu-view' + (menuloading ? ' saving' : '')}>
                 <Card bordered={false} extra={
                   <div className="mk-opeartion-list">
+                    {/* <Dropdown overlay={
+                      <div className="mk-button-dropdown-wrap">
+                        <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
+                      </div>
+                    } trigger={['click']} placement="bottomCenter">
+                      <Button className="mk-button-more">鏇村<DownOutlined/></Button>
+                    </Dropdown> */}
                     {config ? <Debug config={config}/> : null}
                     {config ? <Transfer config={config}/> : null}
                     {config ? <Unattended config={config} updateConfig={this.updateConfig}/> : null}
diff --git a/src/views/tabledesign/popview/index.jsx b/src/views/tabledesign/popview/index.jsx
index 66e3c21..05a7425 100644
--- a/src/views/tabledesign/popview/index.jsx
+++ b/src/views/tabledesign/popview/index.jsx
@@ -68,13 +68,13 @@
     const { oriConfig, config } = this.state
 
     if (!is(fromJS(oriConfig), fromJS(config))) {
-      const _this = this
+      const that = this
 
       confirm({
         title: '閰嶇疆宸蹭慨鏀癸紝鏀惧純淇濆瓨鍚楋紵',
         content: '',
         onOk() {
-          _this.props.cancel()
+          that.props.cancel()
         },
         onCancel() {}
       })

--
Gitblit v1.8.0