From 78eed586f6a0d15162c89878c53a301e7b142a8a Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期一, 10 十月 2022 00:07:06 +0800
Subject: [PATCH] Merge branch 'master' into positec

---
 src/templates/zshare/modalform/index.jsx                                         |   11 
 src/tabviews/formtab/index.jsx                                                   |   19 
 src/menu/components/timeline/normal-timeline/index.jsx                           |   19 
 src/menu/components/card/cardcellcomponent/index.scss                            |    3 
 src/menu/components/card/balcony/options.jsx                                     |   30 
 src/tabviews/zshare/settingcomponent/index.jsx                                   |    5 
 src/templates/zshare/verifycard/customscript/index.jsx                           |    2 
 src/menu/components/share/actioncomponent/dragaction/index.jsx                   |    1 
 src/menu/components/chart/antv-scatter/index.jsx                                 |   33 
 src/templates/modalconfig/index.jsx                                              |   11 
 src/views/systemfunc/header/index.jsx                                            |    2 
 src/tabviews/home/index.jsx                                                      |   63 
 src/templates/sharecomponent/tablecomponent/index.jsx                            |   14 
 src/menu/tablenodes/index.scss                                                   |   54 
 src/tabviews/commontable/index.jsx                                               |   52 
 src/assets/css/design.scss                                                       |    8 
 public/README.txt                                                                |    1 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx             |   28 
 src/menu/datasource/verifycard/index.jsx                                         |   25 
 src/components/header/index.scss                                                 |   29 
 src/tabviews/custom/components/card/cardcellList/index.jsx                       |   21 
 src/tabviews/custom/components/card/prop-card/index.jsx                          |   42 
 src/menu/components/card/cardcellcomponent/index.jsx                             |   15 
 src/menu/components/card/data-card/options.jsx                                   |   27 
 src/store/reducer.js                                                             |   18 
 src/menu/components/form/tab-form/index.jsx                                      |   15 
 src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx   |  208 --
 src/menu/components/carousel/prop-card/index.jsx                                 |   98 -
 src/store/action-type.js                                                         |    6 
 src/tabviews/custom/components/chart/antv-pie/index.jsx                          |   18 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx            |    2 
 src/menu/components/chart/antv-pie/index.jsx                                     |    7 
 src/components/breadview/index.jsx                                               |   16 
 src/tabviews/zshare/mutilform/index.jsx                                          |   84 
 src/menu/components/share/actioncomponent/actionform/index.jsx                   |    5 
 src/menu/components/table/edit-table/columns/index.scss                          |    6 
 src/tabviews/custom/index.jsx                                                    |  368 +--
 src/views/menudesign/index.scss                                                  |   12 
 src/menu/components/card/prop-card/index.jsx                                     |  159 -
 src/templates/zshare/customscript/index.jsx                                      |    8 
 src/tabviews/custom/components/interfaces/index.scss                             |    0 
 src/tabviews/treepage/index.jsx                                                  |   19 
 src/menu/datasource/verifycard/utils.jsx                                         |    2 
 src/assets/css/viewstyle.scss                                                    |    6 
 src/menu/components/card/cardcellcomponent/dragaction/index.scss                 |    1 
 src/menu/datasource/verifycard/index.scss                                        |   12 
 src/tabviews/custom/components/interfaces/interItem/index.scss                   |    0 
 src/menu/components/chart/chart-custom/index.jsx                                 |    7 
 src/menu/components/form/simple-form/index.jsx                                   |   15 
 src/menu/components/chart/antv-bar/index.jsx                                     |   34 
 src/store/action.js                                                              |   16 
 src/tabviews/custom/components/form/simple-form/index.jsx                        |   15 
 src/tabviews/subtable/index.jsx                                                  |   20 
 src/menu/components/table/edit-table/index.jsx                                   |   31 
 src/menu/components/carousel/data-card/index.jsx                                 |   69 
 src/menu/sysinterface/index.jsx                                                  |  138 
 src/templates/zshare/verifycard/index.scss                                       |   14 
 src/tabviews/custom/components/card/table-card/index.jsx                         |   48 
 src/menu/components/form/step-form/index.jsx                                     |   15 
 src/pc/bgcontroller/index.jsx                                                    |   16 
 src/views/pcdesign/index.jsx                                                     |   68 
 src/menu/datasource/verifycard/settingform/index.jsx                             |  216 +-
 src/menu/components/share/actioncomponent/index.jsx                              |   20 
 src/tabviews/custom/components/form/step-form/index.jsx                          |   15 
 src/tabviews/custom/components/interfaces/index.jsx                              |   37 
 src/menu/components/form/dragtitle/card.jsx                                      |    4 
 src/utils/utils-datamanage.js                                                    |    1 
 src/templates/zshare/editTable/index.jsx                                         |   42 
 src/menu/components/table/edit-table/columns/tableIn/index.jsx                   |   27 
 src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx |   12 
 src/menu/components/card/table-card/index.jsx                                    |   78 
 src/components/mkPicture/index.scss                                              |   11 
 src/tabviews/zshare/normalTable/index.jsx                                        |   46 
 src/utils/utils-custom.js                                                        |  167 ++
 src/views/main/index.jsx                                                         |   15 
 src/tabviews/custom/components/share/normalTable/index.scss                      |    7 
 public/options.json                                                              |    1 
 src/menu/datasource/index.jsx                                                    |    5 
 src/tabviews/basetable/index.jsx                                                 |   24 
 src/menu/tablenodes/index.jsx                                                    |  426 +++++
 src/menu/components/tree/antd-tree/index.jsx                                     |    6 
 src/templates/sharecomponent/settingcomponent/settingform/index.jsx              |  123 -
 src/tabviews/subtabtable/index.jsx                                               |   17 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                            |  187 +
 src/views/design/sidemenu/editthdmenu/index.jsx                                  |    1 
 src/views/mobdesign/index.jsx                                                    |   72 
 src/views/menudesign/index.jsx                                                   |   83 
 src/components/mkPicture/index.jsx                                               |   74 
 src/menu/sysinterface/index.scss                                                 |   26 
 src/menu/components/share/actioncomponent/formconfig.jsx                         |   14 
 src/templates/sharecomponent/actioncomponent/actionform/index.jsx                |    5 
 src/menu/components/card/data-card/index.jsx                                     |  105 -
 src/tabviews/custom/components/carousel/prop-card/index.jsx                      |    6 
 src/menu/components/chart/antv-dashboard/index.jsx                               |    6 
 src/views/appmanage/index.jsx                                                    |    3 
 src/views/imdesign/index.jsx                                                     |    3 
 src/menu/components/table/normal-table/index.jsx                                 |   81 
 src/tabviews/zshare/normalTable/index.scss                                       |    9 
 src/components/tabview/index.jsx                                                 |    7 
 src/templates/sharecomponent/settingcomponent/index.jsx                          |    1 
 src/menu/components/share/sourcecomponent/inputform/index.jsx                    |    4 
 src/components/header/index.jsx                                                  |   46 
 src/templates/formtabconfig/index.jsx                                            |   11 
 src/tabviews/custom/components/card/cardItem/index.jsx                           |   48 
 src/tabviews/calendar/index.jsx                                                  |   19 
 src/menu/components/form/dragtitle/index.jsx                                     |    3 
 src/menu/components/chart/chart-custom/chartcompile/index.jsx                    |    4 
 src/tabviews/custom/components/share/normalTable/index.jsx                       |    6 
 src/menu/components/table/normal-table/columns/index.scss                        |    5 
 src/templates/sharecomponent/settingcomponent/settingform/utils.jsx              |    2 
 src/utils/utils.js                                                               |   55 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx            |   33 
 src/index.js                                                                     |   10 
 src/tabviews/custom/components/form/tab-form/index.jsx                           |   15 
 src/menu/components/share/usercomponent/index.jsx                                |    2 
 src/menu/components/card/balcony/index.jsx                                       |   86 
 src/tabviews/zshare/actionList/tabbutton/index.jsx                               |   28 
 src/tabviews/debugtable/index.jsx                                                |  117 +
 src/templates/zshare/formconfig.jsx                                              |   47 
 src/templates/zshare/verifycard/index.jsx                                        |    2 
 src/tabviews/custom/components/interfaces/interItem/index.jsx                    |   73 
 src/templates/sharecomponent/settingcomponent/settingform/index.scss             |    7 
 /dev/null                                                                        |   45 
 src/tabviews/custom/components/table/edit-table/normalTable/index.scss           |   11 
 src/menu/components/editor/braft-editor/index.jsx                                |    5 
 src/tabviews/custom/components/card/balcony/index.jsx                            |   48 
 src/tabviews/custom/components/card/cardcellList/index.scss                      |    9 
 src/menu/components/table/base-table/index.jsx                                   |   61 
 src/tabviews/debugtable/index.scss                                               |   14 
 src/templates/zshare/verifycard/baseform/index.jsx                               |    2 
 src/views/systemfunc/header/index.scss                                           |    6 
 131 files changed, 2,558 insertions(+), 2,340 deletions(-)

diff --git a/public/README.txt b/public/README.txt
index 14e4f03..4c9b587 100644
--- a/public/README.txt
+++ b/public/README.txt
@@ -11,6 +11,7 @@
 defaultLang       -- 鎵撳紑鐨勫瓙搴旂敤璇█绫诲瀷锛岄粯璁や负zh-CN
 WXAppID           -- 浣跨敤鍏紬鍙锋椂锛岀粦瀹氱殑鍏紬鍙稩D
 WXminiAppID       -- 浣跨敤寰俊灏忕▼搴忔椂锛岀粦瀹氱殑灏忕▼搴廔D
+nginx             -- 鏄惁寮�鍚簡nginx鏈嶅姟锛屽�间负 true 鏃跺紑鍚紝濡傞渶浣跨敤寰俊妯℃澘娑堟伅绛夋湇鍔★紝璇峰厛璁剧疆nginx鏈嶅姟骞跺紑鍚閰嶇疆
 debugger          -- 鍊间负 true 鏃跺紑鍚皟璇曟ā寮忥紝寮�鍚悗绉诲姩绔瓙搴旂敤涓細鏈夋帶鍒跺彴
 licenseKey        -- 璁稿彲瀵嗛挜锛屽湪鍐呴儴缃戠粶涓娇鐢ㄧ郴缁熸椂锛屼細璺宠繃epc楠岃瘉
 probation         -- 璇曠敤鏈燂紙YYYY-MM-DD锛夛紝鍦ㄦ寮忕郴缁熶腑锛岃瘯鐢ㄦ湡鍐呰皟鐢ㄧ郴缁熸帴鍙g殑鑴氭湰浼氳褰曚笅鏉�
diff --git a/public/options.json b/public/options.json
index 2b2dba1..955db91 100644
--- a/public/options.json
+++ b/public/options.json
@@ -10,6 +10,7 @@
   "defaultLang": "zh-CN",
   "WXAppID": "wxa5dd6f28cae613fc",
   "WXminiAppID": "",
+  "nginx": "true",
   "debugger": false,
   "licenseKey": "",
   "probation": "",
diff --git a/src/assets/css/design.scss b/src/assets/css/design.scss
index c615204..5d11010 100644
--- a/src/assets/css/design.scss
+++ b/src/assets/css/design.scss
@@ -4,6 +4,7 @@
   }
   .ant-modal-body {
     padding: 0;
+    min-height: 150px;
 
     .mk-com-name {
       position: absolute;
@@ -84,9 +85,4 @@
     height: 200px;
   }
 }
-.mk-color-move {
-  .color-sketch-block {
-    position: relative;
-    top: 7px;
-  }
-}
+
diff --git a/src/assets/css/viewstyle.scss b/src/assets/css/viewstyle.scss
index 33dc189..0f54397 100644
--- a/src/assets/css/viewstyle.scss
+++ b/src/assets/css/viewstyle.scss
@@ -523,6 +523,12 @@
           }
         }
       }
+      .header-menu::-webkit-scrollbar-track {
+        box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.05);
+        border: 1px solid rgba(255, 255, 255, 0.07);
+        background: rgba(255, 255, 255, 255);
+        border-radius: 3px;
+      }
     }
   }
 }
diff --git a/src/components/breadview/index.jsx b/src/components/breadview/index.jsx
index 4e4e3e6..62ae100 100644
--- a/src/components/breadview/index.jsx
+++ b/src/components/breadview/index.jsx
@@ -1,5 +1,4 @@
 import React, {Component} from 'react'
-import {connect} from 'react-redux'
 import { BackTop, Breadcrumb, notification} from 'antd'
 import { HomeOutlined, RightOutlined, RedoOutlined } from '@ant-design/icons'
 import moment from 'moment'
@@ -9,7 +8,6 @@
 import NotFount from '@/components/404'
 import options from '@/store/options.js'
 import MKEmitter from '@/utils/events.js'
-import { initActionPermission } from '@/store/action'
 import Api from '@/api'
 import './index.scss'
 
@@ -57,7 +55,7 @@
               })
             }
   
-            this.props.initActionPermission(_permAction)
+            window.GLOB.mkActions = _permAction
           }
 
           resolve()
@@ -189,14 +187,4 @@
   }
 }
 
-const mapStateToProps = () => {
-  return {}
-}
-
-const mapDispatchToProps = (dispatch) => {
-  return {
-    initActionPermission: (permAction) => dispatch(initActionPermission(permAction)),
-  }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(BreadView)
\ No newline at end of file
+export default BreadView
\ No newline at end of file
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index 6ecc8a9..03f6d5c 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -4,14 +4,12 @@
 import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import moment from 'moment'
-import { Dropdown, Menu, Modal, Form, notification, Switch, Input } from 'antd'
+import { Dropdown, Menu, Modal, notification, Switch, Input } from 'antd'
 import { SearchOutlined, DownOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
 
 import {
   toggleCollapse,
   modifyMainMenu,
-  initActionPermission,
-  initMenuPermission,
   logout
 } from '@/store/action'
 import asyncComponent from '@/utils/asyncSpinComponent'
@@ -185,7 +183,8 @@
       }
 
       this.props.modifyMainMenu(mainMenu)
-      this.props.initMenuPermission([...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}])
+
+      window.GLOB.mkThdMenus = [...thdMenuList, {MenuID: 'home_page_id', EasyCode: '', MenuName: 'home', type: 'CustomPage'}]
 
       if (_menu) { // 寤舵椂鎵撳紑锛岄槻姝㈡爣绛剧粍鏈畬鎴愬姞杞�
         setTimeout(() => {
@@ -196,6 +195,7 @@
           }
         }, 200)
       }
+      MKEmitter.emit('mkMenuLoaded')
     })
     
     // 鑾峰彇瑙掕壊鏉冮檺, edition_type 鎺ュ彛鐗堟湰鎺у埗 ''銆�'Y'銆�'A'
@@ -207,14 +207,14 @@
       }).then(result => {
         let _permAction = {loaded: true} // 鎸夐挳鏉冮檺
 
-        if (result && result.status) {
+        if (result.status) {
           if (result.UserRoles_Menu) {
             result.UserRoles_Menu.forEach(menu => {
               if (!menu.MenuID) return
               _permAction[menu.MenuID] = true
             })
           }
-        } else if (result) {
+        } else {
           notification.error({
             top: 92,
             message: result.message,
@@ -222,7 +222,8 @@
           })
         }
 
-        this.props.initActionPermission(_permAction)
+        MKEmitter.emit('mkActionLoaded')
+        window.GLOB.mkActions = _permAction
       })
     }, 50)
   }
@@ -617,9 +618,9 @@
     return (
       <header className="header-container ant-menu-dark" id="main-header-container">
         <div className={'header-logo ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')} onClick={this.changeToHome}><img src={this.state.logourl} alt=""/></div>
-        <div className={'header-collapse ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')}>
-          {navBar !== 'topmenu' ? (collapse ? <MenuUnfoldOutlined onClick={this.handleCollapse}/> : <MenuFoldOutlined onClick={this.handleCollapse}/>) : null}
-        </div>
+        {navBar !== 'topmenu' ? <div className={'header-collapse ' + (collapse ? 'collapse' : '')}>
+          {collapse ? <MenuUnfoldOutlined onClick={this.handleCollapse}/> : <MenuFoldOutlined onClick={this.handleCollapse}/>}
+        </div> : <div style={{width: '20px', height: '45px'}}></div>}
         {/* 姝e父鑿滃崟 */}
         {navBar !== 'topmenu' && menulist ?
           <ul className="header-menu">{
@@ -713,15 +714,9 @@
             })}
           </ul> : null
         }
-        {/* 澶村儚銆佺敤鎴峰悕 */}
-        <Dropdown className="header-setting" overlay={menu}>
-          <div>
-            <img src={this.state.avatar || avatar} alt=""/>
-            <span>
-              <span className="username"><span>{this.state.fullName}</span>{this.state.userName ? <span>{this.state.userName}</span> : null}</span> <DownOutlined />
-            </span>
-          </div>
-        </Dropdown>
+        {!menulist ?
+          <div className="header-menu"></div> : null
+        }
         {/* 鑿滃崟鎼滅储 */}
         {thdMenuList.length > 0 ?
           <Dropdown overlayClassName="menu-select-dropdown" getPopupContainer={() => document.getElementById('main-header-container')} overlay={
@@ -758,6 +753,15 @@
             <SearchOutlined className="search-menu" />
           </Dropdown> : null
         }
+        {/* 澶村儚銆佺敤鎴峰悕 */}
+        <Dropdown className="header-setting" overlay={menu}>
+          <div>
+            <img src={this.state.avatar || avatar} alt=""/>
+            <span>
+              <span className="username"><span>{this.state.fullName}</span>{this.state.userName ? <span>{this.state.userName}</span> : null}</span> <DownOutlined />
+            </span>
+          </div>
+        </Dropdown>
         {/* 淇敼瀵嗙爜 */}
         <Modal
           title={this.state.dict['main.password']}
@@ -797,10 +801,8 @@
   return {
     toggleCollapse: (collapse) => dispatch(toggleCollapse(collapse)),
     modifyMainMenu: (mainMenu) => dispatch(modifyMainMenu(mainMenu)),
-    initActionPermission: (permAction) => dispatch(initActionPermission(permAction)),
-    initMenuPermission: (permMenus) => dispatch(initMenuPermission(permMenus)),
     logout: () => dispatch(logout())
   }
 }
 
-export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form.create()(Header)))
\ No newline at end of file
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header))
\ No newline at end of file
diff --git a/src/components/header/index.scss b/src/components/header/index.scss
index ee1530d..0c8a8d0 100644
--- a/src/components/header/index.scss
+++ b/src/components/header/index.scss
@@ -6,9 +6,9 @@
   font-weight: bold!important;
   width: 100%;
   height: 48px;
+  display: flex;
 
   .header-logo {
-    float: left;
     width: 180px;
     line-height: 48px;
     text-align: center;
@@ -28,7 +28,6 @@
   }
 
   .header-collapse {
-    float: left;
     width: 35px;
     min-height: 48px;
     line-height: 48px;
@@ -48,13 +47,17 @@
     padding-left: 20px;
   }
   .header-menu {
-    float: left;
     margin: 0;
+    min-height: 20px;
     line-height: 48px;
+    flex: 1;
+    overflow-x: auto;
+    overflow-y: hidden;
+    white-space: nowrap;
     li {
-      float: left;
       font-size: 1.3rem;
       cursor: pointer;
+      display: inline-block;
       span {
         padding: 0 10px;
         height: 42px;
@@ -83,8 +86,22 @@
     }
   }
 
+  .header-menu::-webkit-scrollbar {
+    height: 5px;
+  }
+  .header-menu::-webkit-scrollbar-thumb {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+    border-radius: 5px;
+  }
+  .header-menu::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+    border-radius: 3px;
+  }
+
   .header-setting {
-    float: right;
     line-height: 48px;
     margin-right: 10px;
     img {
@@ -117,10 +134,10 @@
   }
 
   .search-menu {
-    float: right;
     font-size: 18px;
     margin-top: 17px;
     margin-right: 20px;
+    margin-left: 10px;
     cursor: pointer;
   }
   .menu-select-dropdown {
diff --git a/src/components/mkPicture/index.jsx b/src/components/mkPicture/index.jsx
new file mode 100644
index 0000000..6414970
--- /dev/null
+++ b/src/components/mkPicture/index.jsx
@@ -0,0 +1,74 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+
+import LostPng from '@/assets/img/lost.png'
+import MKEmitter from '@/utils/events.js'
+
+import './index.scss'
+
+class MkPicture extends Component {
+  static propTpyes = {
+    style: PropTypes.object,
+    scale: PropTypes.bool,
+    url: PropTypes.string,
+    urls: PropTypes.array,
+  }
+
+  state = {
+    url: '',
+    lost: false
+  }
+
+  UNSAFE_componentWillMount() {
+    const { url } = this.props
+
+    if (url) {
+      this.setState({url: url, lost: false})
+      this.checkUrl(url)
+    } else {
+      this.setState({url: LostPng, lost: true})
+    }
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (nextProps.url) {
+      if (nextProps.url !== this.state.url) {
+        this.setState({url: nextProps.url, lost: false})
+        this.checkUrl(nextProps.url)
+      }
+    } else {
+      this.setState({url: LostPng, lost: true})
+    }
+  }
+
+  checkUrl = (url) => {
+    let img = new Image()
+    img.addEventListener('error', this.loadHandler)
+    img.src = url
+  }
+
+  loadHandler = (e) => {
+    this.setState({url: LostPng, lost: true})
+  }
+
+  render() {
+    const { style, scale, urls } = this.props
+    const { url, lost } = this.state
+
+    return (
+      <div
+        className={'ant-mk-picture' + (scale ? ' scale' : '') + (lost ? ' lost' : '')}
+        onClick={(e) => {
+          if (!scale) return
+
+          e.stopPropagation()
+
+          MKEmitter.emit('mkImageScale', url, urls)
+        }}
+        style={{...style, backgroundImage: `url('${url}')`}}
+      ></div>
+    )
+  }
+}
+
+export default MkPicture
\ No newline at end of file
diff --git a/src/components/mkPicture/index.scss b/src/components/mkPicture/index.scss
new file mode 100644
index 0000000..3d6e51e
--- /dev/null
+++ b/src/components/mkPicture/index.scss
@@ -0,0 +1,11 @@
+.ant-mk-picture {
+  background-size: cover;
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+.ant-mk-picture.lost {
+  background-size: contain!important;
+}
+.ant-mk-picture.scale {
+  cursor: zoom-in;
+}
\ No newline at end of file
diff --git a/src/components/tabview/index.jsx b/src/components/tabview/index.jsx
index 82043c0..ffb0f08 100644
--- a/src/components/tabview/index.jsx
+++ b/src/components/tabview/index.jsx
@@ -7,7 +7,6 @@
 import moment from 'moment'
 import 'moment/locale/zh-cn'
 
-import { initActionPermission } from '@/store/action'
 import asyncComponent from '@/utils/asyncLoadComponent'
 import NotFount from '@/components/404'
 import options from '@/store/options.js'
@@ -101,7 +100,7 @@
               })
             }
   
-            this.props.initActionPermission(_permAction)
+            window.GLOB.mkActions = _permAction
           }
 
           resolve()
@@ -304,9 +303,7 @@
 }
 
 const mapDispatchToProps = (dispatch) => {
-  return {
-    initActionPermission: (permAction) => dispatch(initActionPermission(permAction))
-  }
+  return {}
 }
 
 export default connect(mapStateToProps, mapDispatchToProps)(TabViews)
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index c9434c0..208e800 100644
--- a/src/index.js
+++ b/src/index.js
@@ -73,6 +73,7 @@
     GLOB.watermark = config.watermark + '' !== 'false'
     GLOB.transfer = config.transfer + '' === 'true'
     GLOB.keepKey = config.keepPassword + '' !== 'false'
+    GLOB.nginx = config.nginx + '' === 'true'
     GLOB.WXAppID = config.WXAppID || ''
     GLOB.WXminiAppID = config.WXminiAppID || ''
     GLOB.accessToken = {}
@@ -243,6 +244,15 @@
       }
     }
     GLOB.memberLevel = _level
+    GLOB.mkThdMenus = [] // 涓夌骇鑿滃崟
+    GLOB.mkActions = {}  // 鎸夐挳鏉冮檺闆�
+
+    if (sessionStorage.getItem('breakpoint')) {
+      window.debugger = true
+      GLOB.breakpoint = sessionStorage.getItem('breakpoint')
+    } else {
+      GLOB.breakpoint = false
+    }
 
     Object.defineProperty(GLOB, 'appId', {
       writable: false,
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index 6cec481..0fc9a44 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -2,11 +2,11 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Checkbox } from 'antd'
-import { PlusOutlined, PlusSquareOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, SettingOutlined, ToolOutlined } from '@ant-design/icons'
+import { PlusOutlined, PlusSquareOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, SettingOutlined, ToolOutlined, ClockCircleOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -85,12 +85,31 @@
     return !is(fromJS(this.state), fromJS(nextState))
   }
 
+  componentDidMount () {
+    MKEmitter.addListener('mkUpdateInter', this.mkUpdateInter)
+  }
+
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
    */
   componentWillUnmount () {
     this.setState = () => {
       return
+    }
+    MKEmitter.removeListener('mkUpdateInter', this.mkUpdateInter)
+  }
+
+  mkUpdateInter = (inter, split) => {
+    const { card } = this.state
+    
+    if (card.wrap.datatype === 'public' && card.wrap.publicId === inter.uuid) {
+      let _card = {...card, columns: fromJS(inter.columns).toJS()}
+
+      split.delay = split.delay + 10
+
+      setTimeout(() => {
+        this.updateComponent(_card)
+      }, split.delay)
     }
   }
 
@@ -100,7 +119,6 @@
   updateComponent = (card) => {
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -114,39 +132,35 @@
     card.errors = []
 
     if (card.wrap.datatype === 'static') {
-      // let supModule = card.wrap.linkType === 'static' ? '' : 'has'
-
       card.elements.forEach(cell => {
         if (cell.eleType === 'button') {
           if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
             if (!cell.modal || cell.modal.fields.length === 0) {
               card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            // } else if (!supModule) {
-            //   cell.modal.fields.forEach(m => {
-            //     if (m.type === 'linkMain') {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-            //     }
-            //   })
             }
           }
         } else if (cell.datatype === 'dynamic' && cell.field) {
           card.errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
         }
       })
+      card.$tables = getTables(card)
     } else {
-      // let supModule = card.wrap.linkType === 'static' ? '' : 'has'
-
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
-      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
-        card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
-      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
-        card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
-      } else if (!card.setting.primaryKey) {
-        card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
-      } else if (!columns.includes(card.setting.primaryKey)) {
-        card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+      if (card.wrap.datatype === 'dynamic') {
+        if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
+          card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+        } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
+          card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+        } else if (!card.setting.primaryKey) {
+          card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
+        } else if (!columns.includes(card.setting.primaryKey)) {
+          card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+        }
+      }
+
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
       }
 
       card.elements.forEach(cell => {
@@ -154,14 +168,6 @@
           if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
             if (!cell.modal || cell.modal.fields.length === 0) {
               card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            // } else {
-            //   cell.modal.fields.forEach(m => {
-            //     if (m.type === 'linkMain' && !supModule) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-            //     } else if (m.field && card.wrap.linkType !== 'sync' && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-            //     }
-            //   })
             }
           }
         } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -249,7 +255,20 @@
 
   updateWrap = (res) => {
     delete res.quick
-    this.updateComponent({...this.state.card, wrap: res})
+
+    let _card = {...this.state.card, wrap: res}
+
+    if (res.datatype === 'public') {
+      let interfaces = window.GLOB.customMenu.interfaces || []
+
+      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
+
+      if (d) {
+        _card.columns = fromJS(d.columns).toJS()
+      }
+    }
+
+    this.updateComponent(_card)
   }
 
   render() {
@@ -269,11 +288,10 @@
             <CopyComponent type="balcony" card={card}/>
             <PasteComponent options={['action', 'customCardElement']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} />
-            <ClockComponent config={card} updateConfig={this.updateComponent}/>
+            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
-            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
-            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
+            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
         } trigger="hover">
           <ToolOutlined />
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index aab6ad8..c39fa7b 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -6,10 +6,24 @@
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
  */
 export default function (wrap) {
-  let modules = MenuUtils.getLinkModules(fromJS(window.GLOB.customMenu).toJS().components) || []
-  let supmodules = MenuUtils.getSupModules(fromJS(window.GLOB.customMenu).toJS().components, '') || []
+  let menu = fromJS(window.GLOB.customMenu).toJS()
+
+  let modules = MenuUtils.getLinkModules(menu.components) || []
+  let supmodules = MenuUtils.getSupModules(menu.components, '') || []
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
+
+  let interfaces = []
+  if (menu.interfaces) {
+    menu.interfaces.forEach(item => {
+      if (item.status === 'true') {
+        interfaces.push({
+          value: item.uuid,
+          label: item.name
+        })
+      }
+    })
+  }
 
   if (roleList) {
     try {
@@ -51,12 +65,22 @@
       options: [
         {value: 'dynamic', label: '鍔ㄦ��'},
         {value: 'static', label: '闈欐��'},
+        {value: 'public', label: '鍏叡鏁版嵁婧�'},
       ],
       controlFields: [
-        {field: 'empty', values: ['dynamic']}
+        {field: 'empty', values: ['dynamic']},
+        {field: 'publicId', values: ['public']},
       ]
     },
     {
+      type: 'select',
+      field: 'publicId',
+      label: '鏁版嵁婧�',
+      initval: wrap.publicId || '',
+      required: true,
+      options: interfaces
+    },
+    {
       type: 'radio',
       field: 'linkType',
       label: '鍙楁帶绫诲瀷',
diff --git a/src/menu/components/card/cardcellcomponent/dragaction/index.scss b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
index ea8410f..3683516 100644
--- a/src/menu/components/card/cardcellcomponent/dragaction/index.scss
+++ b/src/menu/components/card/cardcellcomponent/dragaction/index.scss
@@ -114,7 +114,6 @@
     background-size: cover;
     background-position: center center;
     background-repeat: no-repeat;
-    background-color: #f5f5f5;
   }
   .ant-mk-icon {
     vertical-align: top;
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index ce15a0c..c00048b 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -297,17 +297,6 @@
       <p style={{marginBottom: '5px'}}>{this.state.dict['model.tooltip.func.innerface'].replace('@ableField', ableField)}</p>
     </div>
 
-    let menulist = sessionStorage.getItem('fstMenuList')
-    if (menulist) {
-      try {
-        menulist = JSON.parse(menulist)
-      } catch (e) {
-        menulist = []
-      }
-    } else {
-      menulist = []
-    }
-
     let supId = ''
     if (cards.setting && cards.setting.supModule) {
       let pid = cards.setting.supModule[cards.setting.supModule.length - 1]
@@ -324,7 +313,7 @@
     this.setState({
       actvisible: true,
       card: card,
-      formlist: getActionForm(card, functip, cards, usefulFields, menulist, modules, anchors)
+      formlist: getActionForm(card, functip, cards, usefulFields, modules, anchors)
     })
   }
 
@@ -487,8 +476,6 @@
         if (card.OpenType === 'popview' || card.verify || card.modal) {
           card.$parentId = cardCell.uuid
           card.$side = side || ''
-
-          // MKEmitter.emit('logButton', cards.uuid, card)
         }
 
         _this.setState({
diff --git a/src/menu/components/card/cardcellcomponent/index.scss b/src/menu/components/card/cardcellcomponent/index.scss
index 30af64f..e97d0e2 100644
--- a/src/menu/components/card/cardcellcomponent/index.scss
+++ b/src/menu/components/card/cardcellcomponent/index.scss
@@ -3,6 +3,9 @@
   .ant-btn {
     padding: 0;
   }
+  .card-detail-row {
+    min-height: 16px;
+  }
 
   .card-button-cell {
     float: left;
diff --git a/src/menu/components/card/data-card/index.jsx b/src/menu/components/card/data-card/index.jsx
index 09d308d..97156e8 100644
--- a/src/menu/components/card/data-card/index.jsx
+++ b/src/menu/components/card/data-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -16,7 +16,6 @@
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardComponent = asyncComponent(() => import('../cardcomponent'))
 const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
@@ -64,7 +63,6 @@
         scripts: [],
         action: [],
         search: [],
-        btnlog: [],
         subcards: [{
           uuid: Utils.getuuid(),
           setting: { width: appType === 'mob' ? 24 : 6, type: 'simple'},
@@ -147,7 +145,6 @@
 
   componentDidMount () {
     MKEmitter.addListener('submitModal', this.handleSave)
-    // MKEmitter.addListener('logButton', this.logButton)
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -162,20 +159,8 @@
       return
     }
     MKEmitter.removeListener('submitModal', this.handleSave)
-    // MKEmitter.removeListener('logButton', this.logButton)
   }
 
-  // logButton = (id, item) => {
-  //   const { card } = this.state
-
-  //   if (id !== card.uuid) return
-
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
-  
   /**
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
@@ -184,7 +169,6 @@
 
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -197,7 +181,6 @@
 
     card.errors = []
     let columns = card.columns.map(c => c.field)
-    // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
     if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
       card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -210,31 +193,15 @@
     } else if (card.wrap.supType !== 'multi' && !card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
-
-    // let supModule = ''
-    // if (card.wrap.supType === 'multi') { // 鏁版嵁鍗″涓婄骇缁勪欢
-    //   if (card.supNodes && card.supNodes[0]) {
-    //     supModule = card.supNodes[0].componentId
-    //   }
-    // } else if (card.setting.supModule) {
-    //   supModule = card.setting.supModule[card.setting.supModule.length - 1] || ''
-    //   if (supModule === 'empty') {
-    //     supModule = ''
-    //   }
-    // }
+    
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
 
     card.action.forEach(cell => {
       if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
         if (!cell.modal || cell.modal.fields.length === 0) {
           card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-        // } else {
-        //   cell.modal.fields.forEach(m => {
-        //     if (m.type === 'linkMain' && !supModule) {
-        //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-        //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-        //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-        //     }
-        //   })
         }
       }
       // $check@鏈夋晥鎬ф娴�
@@ -256,14 +223,6 @@
           if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
             if (!cell.modal || cell.modal.fields.length === 0) {
               card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            // } else {
-            //   cell.modal.fields.forEach(m => {
-            //     if (m.type === 'linkMain' && !supModule) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-            //     }
-            //   })
             }
           }
           if (linkbtn && linkbtn === cell.uuid) {
@@ -280,14 +239,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
             if (linkbtn && linkbtn === cell.uuid) {
@@ -341,10 +292,6 @@
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
-
-        // if (card.btnlog) {
-        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
-        // }
 
         _this.updateComponent(card)
 
@@ -478,47 +425,6 @@
 
     this.updateComponent(card)
   }
-
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.subcards.forEach(col => {
-  //         if (item.$parentId === col.uuid) {
-  //           if (item.$side !== 'back') {
-  //             col.elements = col.elements ? [...col.elements, item] : [item]
-  //           } else {
-  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
-  //           }
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     if (!done) {
-  //       card.action = card.action ? [...card.action, item] : [item]
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
 
   addCard = (copy) => {
     let card = fromJS(this.state.card).toJS()
@@ -779,7 +685,6 @@
             <CopyComponent type="datacard" card={card}/>
             <PasteComponent options={['action', 'search', 'form', 'cardcell']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index 7db4e04..3733162 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -9,6 +9,17 @@
   let MenuType = ''
   let menu = fromJS(window.GLOB.customMenu).toJS()
   let laypage = setting && setting.laypage !== 'false'
+  let interfaces = []
+  if (subtype === 'propcard' && menu.interfaces) {
+    menu.interfaces.forEach(item => {
+      if (item.status === 'true') {
+        interfaces.push({
+          value: item.uuid,
+          label: item.name
+        })
+      }
+    })
+  }
 
   if (menu.parentId === 'BillPrintTemp') {
     MenuType = 'billPrint'
@@ -82,14 +93,25 @@
       options: [
         {value: 'dynamic', label: '鍔ㄦ��', priKeyType: 'static'},
         {value: 'static', label: '闈欐��', priKeyType: 'static'},
+        {value: 'public', label: '鍏叡鏁版嵁婧�', priKeyType: 'static'},
       ],
       linkFields: ['priKeyType'],
       controlFields: [
         {field: 'goback', values: ['dynamic']},
-        {field: 'empty', values: ['dynamic']},
+        {field: 'empty', values: ['dynamic', 'public']},
         {field: 'jump', values: ['dynamic']},
         {field: 'supModule', values: ['static']},
+        {field: 'publicId', values: ['public']},
       ],
+      forbid: subtype !== 'propcard'
+    },
+    {
+      type: 'select',
+      field: 'publicId',
+      label: '鏁版嵁婧�',
+      initval: wrap.publicId || '',
+      required: true,
+      options: interfaces,
       forbid: subtype !== 'propcard'
     },
     {
@@ -160,6 +182,9 @@
         {ParentID: 'dynamic', value: 'static', label: '闈欐�佸��'},
         {ParentID: 'dynamic', value: 'dynamic', label: '鍔ㄦ�佸��'},
         {ParentID: 'dynamic', value: 'joint', label: '鎷兼帴鍊�'},
+        {ParentID: 'public', value: 'static', label: '闈欐�佸��'},
+        {ParentID: 'public', value: 'dynamic', label: '鍔ㄦ�佸��'},
+        {ParentID: 'public', value: 'joint', label: '鎷兼帴鍊�'},
       ],
       forbid: subtype !== 'propcard'
     },
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index daf0cb9..e79cbe6 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -2,11 +2,11 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Modal } from 'antd'
-import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, ClockCircleOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -17,7 +17,6 @@
 const CardComponent = asyncComponent(() => import('../cardcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -72,7 +71,6 @@
           elements: [],
           backElements: []
         }],
-        btnlog: [],
       }
 
       if (card.config) {
@@ -109,7 +107,7 @@
   }
 
   componentDidMount () {
-    // MKEmitter.addListener('logButton', this.logButton)
+    MKEmitter.addListener('mkUpdateInter', this.mkUpdateInter)
     MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
   }
 
@@ -124,7 +122,7 @@
     this.setState = () => {
       return
     }
-    // MKEmitter.removeListener('logButton', this.logButton)
+    MKEmitter.removeListener('mkUpdateInter', this.mkUpdateInter)
     MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
   }
 
@@ -145,17 +143,19 @@
     })
   }
 
-  // 鎸夐挳鍘嗗彶璁板綍
-  // logButton = (id, item) => {
-  //   const { card } = this.state
+  mkUpdateInter = (inter, split) => {
+    const { card } = this.state
+    
+    if (card.wrap.datatype === 'public' && card.wrap.publicId === inter.uuid) {
+      let _card = {...card, columns: fromJS(inter.columns).toJS()}
 
-  //   if (id !== card.uuid) return
+      split.delay = split.delay + 10
 
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
+      setTimeout(() => {
+        this.updateComponent(_card)
+      }, split.delay)
+    }
+  }
 
   /**
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
@@ -165,7 +165,6 @@
 
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -183,7 +182,8 @@
     }
 
     if (card.wrap.datatype === 'static') {
-      // let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
+      card.$tables = getTables(card)
+
       card.subcards.forEach((item, i) => {
         let linkbtn = item.setting.linkbtn || ''
 
@@ -192,12 +192,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else if (!supModule) {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain') {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     }
-              //   })
               }
             }
             if (linkbtn && linkbtn === cell.uuid) {
@@ -214,12 +208,6 @@
               if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                 if (!cell.modal || cell.modal.fields.length === 0) {
                   card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-                // } else if (!supModule) {
-                //   cell.modal.fields.forEach(m => {
-                //     if (m.type === 'linkMain') {
-                //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-                //     }
-                //   })
                 }
               }
               if (linkbtn && linkbtn === cell.uuid) {
@@ -236,23 +224,24 @@
         }
       })
     } else {
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
-      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
-        card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
-      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
-        card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
-      } else if (!card.setting.primaryKey) {
-        card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
-      } else if (!columns.includes(card.setting.primaryKey)) {
-        card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
-      } else if (!card.setting.supModule) {
-        card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+      if (card.wrap.datatype === 'dynamic') {
+        if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
+          card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+        } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
+          card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+        } else if (!card.setting.primaryKey) {
+          card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
+        } else if (!columns.includes(card.setting.primaryKey)) {
+          card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+        } else if (!card.setting.supModule) {
+          card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+        }
+      }
+
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
       }
 
       card.subcards.forEach((item, i) => {
@@ -262,14 +251,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
             if (linkbtn && linkbtn === cell.uuid) {
@@ -286,14 +267,6 @@
               if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                 if (!cell.modal || cell.modal.fields.length === 0) {
                   card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-                // } else {
-                //   cell.modal.fields.forEach(m => {
-                //     if (m.type === 'linkMain' && !supModule) {
-                //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-                //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-                //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-                //     }
-                //   })
                 }
               }
               if (linkbtn && linkbtn === cell.uuid) {
@@ -344,10 +317,6 @@
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
-
-        // if (card.btnlog) {
-        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
-        // }
 
         _this.updateComponent(card)
 
@@ -424,53 +393,6 @@
 
     this.updateComponent(card)
   }
-
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.subcards.forEach(col => {
-  //         if (item.$parentId === col.uuid) {
-  //           if (item.$side !== 'back') {
-  //             col.elements = col.elements ? [...col.elements, item] : [item]
-  //           } else {
-  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
-  //           }
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.setState({ card: {...card, subcards: []} }, () => {
-  //       this.updateComponent(card)
-  //     })
-  //     if (!done) {
-  //       notification.warning({
-  //         top: 92,
-  //         message: '闄勫睘鍗$墖宸插垹闄わ紒',
-  //         duration: 2
-  //       })
-  //     } else {
-  //       notification.success({
-  //         top: 92,
-  //         message: '鎭㈠鎴愬姛锛�',
-  //         duration: 2
-  //       })
-  //     }
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
 
   move = (item, direction) => {
     let card = fromJS(this.state.card).toJS()
@@ -580,7 +502,16 @@
       } else {
         _card.setting.supModule = ''
       }
+    } else if (res.datatype === 'public') {
+      let interfaces = window.GLOB.customMenu.interfaces || []
+
+      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
+
+      if (d) {
+        _card.columns = fromJS(d.columns).toJS()
+      }
     }
+
     if (res.layout === 'flex') {
       _card.wrap.pagestyle = 'page'
     }
@@ -631,12 +562,10 @@
             <CopyComponent type="propcard" card={card}/>
             <PasteComponent options={['cardcell']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
-            <ClockComponent config={card} updateConfig={this.updateComponent}/>
+            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
-            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
-            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
+            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
         } trigger="hover">
           <ToolOutlined />
diff --git a/src/menu/components/card/table-card/index.jsx b/src/menu/components/card/table-card/index.jsx
index 689e208..0775056 100644
--- a/src/menu/components/card/table-card/index.jsx
+++ b/src/menu/components/card/table-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -18,7 +18,6 @@
 const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
@@ -71,7 +70,6 @@
           elements: []
         }],
         action: [],
-        btnlog: [],
       }
       
       if (card.config) {
@@ -150,24 +148,12 @@
     }
   }
 
-  // logButton = (id, item) => {
-  //   const { card } = this.state
-
-  //   if (id !== card.uuid) return
-
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
-
   /**
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
   updateComponent = (card) => {
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -203,6 +189,10 @@
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
 
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
+
     card.subcards.forEach((item, i) => {
       let linkbtn = item.setting.linkbtn || ''
       item.elements.forEach(cell => {
@@ -210,14 +200,6 @@
           if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
             if (!cell.modal || cell.modal.fields.length === 0) {
               card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            // } else {
-            //   cell.modal.fields.forEach(m => {
-            //     if (m.type === 'linkMain' && !supModule) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-            //     }
-            //   })
             }
           }
           if (linkbtn && linkbtn === cell.uuid) {
@@ -266,10 +248,6 @@
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
-
-        // if (card.btnlog) {
-        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
-        // }
 
         _this.updateComponent(card)
 
@@ -358,51 +336,6 @@
     // 娉ㄥ唽浜嬩欢-娣诲姞鎼滅储
     MKEmitter.emit('addSearch', card.uuid, newcard)
   }
-
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.subcards.forEach(col => {
-  //         if (item.$parentId === col.uuid) {
-  //           if (item.$side !== 'back') {
-  //             col.elements = col.elements ? [...col.elements, item] : [item]
-  //           } else {
-  //             col.backElements = col.backElements ? [...col.backElements, item] : [item]
-  //           }
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     if (!done) {
-  //       notification.warning({
-  //         top: 92,
-  //         message: '闄勫睘鍗$墖宸插垹闄わ紒',
-  //         duration: 2
-  //       })
-  //     } else {
-  //       notification.success({
-  //         top: 92,
-  //         message: '鎭㈠鎴愬姛锛�',
-  //         duration: 2
-  //       })
-  //     }
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
 
   move = (item, direction) => {
     let card = fromJS(this.state.card).toJS()
@@ -589,7 +522,6 @@
             <CopyComponent type="tablecard" card={card}/>
             <PasteComponent options={['cardcell', 'search', 'form']} updateConfig={this.pasteComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/carousel/data-card/index.jsx b/src/menu/components/carousel/data-card/index.jsx
index 0a4ad64..9d5f891 100644
--- a/src/menu/components/carousel/data-card/index.jsx
+++ b/src/menu/components/carousel/data-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -15,7 +15,6 @@
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
@@ -56,7 +55,6 @@
         style: { borderWidth: '1px', borderColor: '#e8e8e8', marginTop: '8px', marginBottom: '8px', height: '300px' },
         columns: [],
         scripts: [],
-        btnlog: [],
         subcards: [{
           uuid: Utils.getuuid(),
           setting: {},
@@ -109,24 +107,12 @@
     }
   }
 
-  // logButton = (id, item) => {
-  //   const { card } = this.state
-
-  //   if (id !== card.uuid) return
-
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
-  
   /**
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
   updateComponent = (card) => {
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -139,13 +125,7 @@
 
     card.errors = []
 
-    // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-    // if (supModule === 'empty') {
-    //   supModule = ''
-    // }
-
     let columns = card.columns.map(c => c.field)
-    // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
     if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
       card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -159,20 +139,16 @@
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
 
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
+
     card.subcards.forEach((item, i) => {
       item.elements.forEach(cell => {
         if (cell.eleType === 'button') {
           if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
             if (!cell.modal || cell.modal.fields.length === 0) {
               card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            // } else {
-            //   cell.modal.fields.forEach(m => {
-            //     if (m.type === 'linkMain' && !supModule) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-            //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-            //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-            //     }
-            //   })
             }
           }
         } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -215,10 +191,6 @@
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
 
-        // if (card.btnlog) {
-        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
-        // }
-
         _this.updateComponent(card)
 
         if (appType === 'mob') return
@@ -251,36 +223,6 @@
     this.updateComponent(_card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     card.subcards.forEach(col => {
-  //       col.elements = [...col.elements, item]
-  //       if (item.$parentId === col.uuid) {
-  //         col.elements = [...col.elements, item]
-  //       }
-  //     })
-
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   getWrapForms = () => {
     const { card } = this.state
 
@@ -311,7 +253,6 @@
             </NormalForm>
             <CopyComponent type="datacard" card={card}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)}/>
diff --git a/src/menu/components/carousel/prop-card/index.jsx b/src/menu/components/carousel/prop-card/index.jsx
index 685c304..2c55db0 100644
--- a/src/menu/components/carousel/prop-card/index.jsx
+++ b/src/menu/components/carousel/prop-card/index.jsx
@@ -2,11 +2,11 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Modal, Carousel } from 'antd'
-import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined, ClockCircleOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -17,7 +17,6 @@
 const CardSimpleComponent = asyncComponent(() => import('@/menu/components/card/cardsimplecomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 
@@ -62,8 +61,7 @@
           setting: {},
           style: {},
           elements: [],
-        }],
-        btnlog: [],
+        }]
       }
 
       if (card.config) {
@@ -96,7 +94,6 @@
   }
 
   componentDidMount () {
-    // MKEmitter.addListener('logButton', this.logButton)
     MKEmitter.addListener('submitComponentStyle', this.updateComponentStyle)
   }
 
@@ -111,7 +108,6 @@
     this.setState = () => {
       return
     }
-    // MKEmitter.removeListener('logButton', this.logButton)
     MKEmitter.removeListener('submitComponentStyle', this.updateComponentStyle)
   }
 
@@ -132,24 +128,12 @@
     })
   }
 
-  // logButton = (id, item) => {
-  //   const { card } = this.state
-
-  //   if (id !== card.uuid) return
-
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
-
   /**
    * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
    */
   updateComponent = (card) => {
     card.width = card.wrap.width
     card.name = card.wrap.name
-    card.btnlog = []
 
     if (window.GLOB.styling && card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       this.setState({
@@ -167,18 +151,13 @@
     }
 
     if (card.wrap.datatype === 'static') {
+      card.$tables = getTables(card)
       card.subcards.forEach(item => {
         item.elements.forEach(cell => {
           if (cell.eleType === 'button') {
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain') {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     }
-              //   })
               }
             }
           } else if (cell.datatype === 'dynamic' && cell.field) {
@@ -187,12 +166,7 @@
         })
       })
     } else {
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -206,20 +180,16 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.subcards.forEach((item, i) => {
         item.elements.forEach(cell => {
           if (cell.eleType === 'button') {
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
           } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
@@ -262,10 +232,6 @@
       content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
       onOk() {
         card.subcards = card.subcards.filter(item => item.uuid !== cell.uuid)
-
-        // if (card.btnlog) {
-        //   card.btnlog = card.btnlog.filter(c => c.$parentId !== cell.uuid)
-        // }
 
         _this.updateComponent(card)
 
@@ -323,49 +289,6 @@
     this.updateComponent(card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.subcards.forEach(col => {
-  //         if (item.$parentId === col.uuid) {
-  //           col.elements = [...col.elements, item]
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.setState({ card: {...card, subcards: []} }, () => {
-  //       this.updateComponent(card)
-  //     })
-  //     if (!done) {
-  //       notification.warning({
-  //         top: 92,
-  //         message: '闄勫睘鍗$墖宸插垹闄わ紒',
-  //         duration: 2
-  //       })
-  //     } else {
-  //       notification.success({
-  //         top: 92,
-  //         message: '鎭㈠鎴愬姛锛�',
-  //         duration: 2
-  //       })
-  //     }
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   move = (item, direction) => {
     let card = fromJS(this.state.card).toJS()
 
@@ -419,12 +342,11 @@
             <CopyComponent type="propcard" card={card}/>
             <PasteComponent config={card} options={['cardcell']} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
+            {card.wrap.datatype === 'dynamic' ? <ClockComponent config={card} updateConfig={this.updateComponent}/> : <ClockCircleOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
-            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
-            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
+            {card.wrap.datatype === 'dynamic' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/>}
           </div>
         } trigger="hover">
           <ToolOutlined/>
diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index acd5cc0..ca91e00 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -9,7 +9,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import { chartColors } from '@/utils/option.js'
 import zhCN from '@/locales/zh-CN/model.js'
@@ -18,7 +18,6 @@
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -91,7 +90,6 @@
         search: [],
         action: [],
         plot: _plot,
-        btnlog: [],
       }
 
       if (card.config) {
@@ -1228,7 +1226,6 @@
 
     card.width = card.plot.width
     card.name = card.plot.name
-    card.btnlog = []
     card.errors = []
 
     let columns = card.columns.map(c => c.field)
@@ -1243,6 +1240,10 @@
       card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
     } else if (!card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+    }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
     }
     
     if (!card.plot.Xaxis) {
@@ -1345,30 +1346,6 @@
     this.updateComponent(_card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     card.action = card.action ? [...card.action, item] : [item]
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   clickComponent = (e) => {
     if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
       e.stopPropagation()
@@ -1390,7 +1367,6 @@
             <CopyComponent type="line" card={card}/>
             <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/chart/antv-dashboard/index.jsx b/src/menu/components/chart/antv-dashboard/index.jsx
index 6434bd4..2e5d021 100644
--- a/src/menu/components/chart/antv-dashboard/index.jsx
+++ b/src/menu/components/chart/antv-dashboard/index.jsx
@@ -8,7 +8,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
 import './index.scss'
@@ -494,6 +494,10 @@
     } else if (!card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
     
     if (!card.plot.valueField) {
       card.errors.push({ level: 0, detail: '鏄剧ず鍊煎皻鏈缃紒'})
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
index 1fdd69b..88d312e 100644
--- a/src/menu/components/chart/antv-pie/index.jsx
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -9,7 +9,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
@@ -83,7 +83,6 @@
         search: [],
         action: [],
         plot: _plot,
-        btnlog: [],
       }
 
       if (card.config) {
@@ -628,6 +627,10 @@
     } else if (!card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
     
     if (!card.plot.Xaxis) {
       card.errors.push({ level: 0, detail: '鍚嶇О瀛楁灏氭湭璁剧疆锛�'})
diff --git a/src/menu/components/chart/antv-scatter/index.jsx b/src/menu/components/chart/antv-scatter/index.jsx
index e5b1dfa..21f09bc 100644
--- a/src/menu/components/chart/antv-scatter/index.jsx
+++ b/src/menu/components/chart/antv-scatter/index.jsx
@@ -8,7 +8,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
@@ -16,7 +16,6 @@
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
 const ChartCompileForm = asyncIconComponent(() => import('./chartcompile'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
@@ -78,7 +77,6 @@
         search: [],
         action: [],
         plot: _plot,
-        btnlog: [],
       }
 
       if (card.config) {
@@ -276,6 +274,10 @@
     } else if (!card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
     
     if (!card.plot.Xaxis) {
       card.errors.push({ level: 0, detail: '鍧愭爣杞村皻鏈缃紒'})
@@ -363,30 +365,6 @@
     this.updateComponent(_card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     card.action = card.action ? [...card.action, item] : [item]
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   clickComponent = (e) => {
     if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
       e.stopPropagation()
@@ -408,7 +386,6 @@
             <CopyComponent type="line" card={card}/>
             <PasteComponent config={card} options={['action', 'search']} updateConfig={this.updateComponent}/>
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog}/> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/>
diff --git a/src/menu/components/chart/chart-custom/chartcompile/index.jsx b/src/menu/components/chart/chart-custom/chartcompile/index.jsx
index 2f0871c..fd2e219 100644
--- a/src/menu/components/chart/chart-custom/chartcompile/index.jsx
+++ b/src/menu/components/chart/chart-custom/chartcompile/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Modal, Form, Tabs } from 'antd'
+import { Modal, Tabs } from 'antd'
 import { EditOutlined } from '@ant-design/icons'
 
 import { getBaseForm } from './formconfig'
@@ -118,4 +118,4 @@
   }
 }
 
-export default Form.create()(CustomChartDrawerForm)
\ No newline at end of file
+export default CustomChartDrawerForm
\ No newline at end of file
diff --git a/src/menu/components/chart/chart-custom/index.jsx b/src/menu/components/chart/chart-custom/index.jsx
index 8de9dd0..ea9e578 100644
--- a/src/menu/components/chart/chart-custom/index.jsx
+++ b/src/menu/components/chart/chart-custom/index.jsx
@@ -10,7 +10,7 @@
 import MKEmitter from '@/utils/events.js'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import Utils from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
@@ -70,7 +70,6 @@
         search: [],
         action: [],
         plot: _plot,
-        btnlog: [],
       }
 
       if (card.config) {
@@ -205,6 +204,10 @@
     } else if (!card.setting.supModule) {
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
+
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
     
     this.setState({
       card: card
diff --git a/src/menu/components/editor/braft-editor/index.jsx b/src/menu/components/editor/braft-editor/index.jsx
index 6d7e1d7..4949f0c 100644
--- a/src/menu/components/editor/braft-editor/index.jsx
+++ b/src/menu/components/editor/braft-editor/index.jsx
@@ -6,6 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
+import { getTables } from '@/utils/utils-custom.js'
 import getWrapForm from './options'
 import MKEmitter from '@/utils/events.js'
 
@@ -114,6 +115,10 @@
       } else if (!card.setting.supModule) {
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
+
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
     }
 
     this.setState({
diff --git a/src/menu/components/form/dragtitle/card.jsx b/src/menu/components/form/dragtitle/card.jsx
index 63a8d4b..090ccd1 100644
--- a/src/menu/components/form/dragtitle/card.jsx
+++ b/src/menu/components/form/dragtitle/card.jsx
@@ -11,7 +11,7 @@
 const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 
-const Card = ({ id, card, active, moveCard, findCard, closeCard, selectCard, updateGroup }) => {
+const Card = ({ id, card, sort, active, moveCard, findCard, closeCard, selectCard, updateGroup }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
     item: { type: 'form', id, originalIndex },
@@ -80,7 +80,7 @@
     } trigger="hover">
       <div className={'page-card ' + (active ? 'active' : '')} onClick={select} style={{ opacity: opacity}}>
         <div ref={node => drag(drop(node))}>
-          <span className="form-sort">{card.sort}</span>
+          <span className="form-sort">{sort}</span>
           {card.setting.title}
         </div>
       </div>
diff --git a/src/menu/components/form/dragtitle/index.jsx b/src/menu/components/form/dragtitle/index.jsx
index 138a259..96a6e7f 100644
--- a/src/menu/components/form/dragtitle/index.jsx
+++ b/src/menu/components/form/dragtitle/index.jsx
@@ -40,10 +40,11 @@
 
   return (
     <div className={'normal-form-titles ' + (tabtype || '') } >
-      {cards.map(card => (
+      {cards.map((card, i) => (
         <Card
           id={card.uuid}
           key={card.uuid}
+          sort={i + 1}
           active={card.uuid === selectId}
           card={card}
           moveCard={moveCard}
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 7aa4c24..599291c 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -160,7 +160,6 @@
         supModule = ''
       }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -174,22 +173,26 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //   card.errors.push({ level: 1, detail: `琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ叧鑱斾富琛ㄢ��${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
     } else {
       let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
 
+      card.$tables = getTables(card)
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ叧鑱斾富琛ㄢ��${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index 4ccf43c..00d3501 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -167,7 +167,6 @@
         supModule = ''
       }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -181,22 +180,26 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //   card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ垎缁勨��${item.setting.title}鈥濅腑鍏宠仈涓昏〃鈥�${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
     } else {
       let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
 
+      card.$tables = getTables(card)
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ垎缁勨��${item.setting.title}鈥濅腑鍏宠仈涓昏〃鈥�${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index 711552c..a553bdc 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -9,7 +9,7 @@
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../step-form/options'
@@ -179,7 +179,6 @@
         supModule = ''
       }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -193,22 +192,26 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          // } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //   card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ垎缁勨��${item.setting.title}鈥濅腑鍏宠仈涓昏〃鈥�${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
     } else {
       let supModule = card.wrap.supModule ? card.wrap.supModule[card.wrap.supModule.length - 1] : ''
 
+      card.$tables = getTables(card)
+
       card.subcards.forEach(item => {
         item.fields.forEach(m => {
           if (m.type === 'linkMain' && !supModule) {
-            card.errors.push({ level: 1, detail: `鍒嗙粍鈥�${item.setting.title}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
+            card.errors.push({ level: 1, detail: `璇锋鏌ュ垎缁勨��${item.setting.title}鈥濅腑鍏宠仈涓昏〃鈥�${m.label}鈥濇槸鍚︽湁鏁坄})
           }
         })
       })
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index 29dcf6e..eb99135 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -734,6 +734,11 @@
             { pattern: _patten, message: formRule.func.innerMessage },
             { max: formRule.func.max, message: formRule.func.maxMessage }
           )
+        } else if (item.key === 'sql' || item.key === 'sheet') {
+          rules.push(
+            { pattern: /^[a-zA-Z_]+$/, message: '琛ㄥ悕鍙彲浣跨敤瀛楁瘝浠ュ強_' },
+            { max: formRule.func.max, message: formRule.func.maxMessage }
+          )
         } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
           rules.push(
             { pattern: formRule.func.pattern, message: formRule.func.message },
diff --git a/src/menu/components/share/actioncomponent/dragaction/index.jsx b/src/menu/components/share/actioncomponent/dragaction/index.jsx
index 4ea521d..d52c80d 100644
--- a/src/menu/components/share/actioncomponent/dragaction/index.jsx
+++ b/src/menu/components/share/actioncomponent/dragaction/index.jsx
@@ -119,6 +119,7 @@
           newcard.Ot = 'requiredSgl'
           newcard.OpenType = item.value
           newcard.class = 'primary'
+          newcard.style = { marginRight: '15px' }
 
           if (newcard.OpenType === 'excelIn') {
             newcard.label = item.text
diff --git a/src/menu/components/share/actioncomponent/formconfig.jsx b/src/menu/components/share/actioncomponent/formconfig.jsx
index 970a91a..a8f146a 100644
--- a/src/menu/components/share/actioncomponent/formconfig.jsx
+++ b/src/menu/components/share/actioncomponent/formconfig.jsx
@@ -12,7 +12,7 @@
  * @param {*} usefulFields   瀛樺偍杩囩▼鍙敤鐨勫紑濮嬪瓧娈�
  * @param {*} type           鎸夐挳绫诲瀷锛岀敤浜庡尯鍒嗗彲閫夌殑鎵撳紑鏂瑰紡
  */
-export function getActionForm (card, functip, config, usefulFields, menulist = [], modules = [], anchors = []) {
+export function getActionForm (card, functip, config, usefulFields, modules = [], anchors = []) {
   let appType = sessionStorage.getItem('appType')
   let viewType = sessionStorage.getItem('editMenuType') // 寮圭獥 popview
   let printTemps = sessionStorage.getItem('printTemps')
@@ -20,6 +20,7 @@
   let setting = config.setting || {}
   let columns = config.columns || []
   let appMenus = []
+  let menulist = []
   let type = ''
 
   if (card.eleType === 'button') {
@@ -115,6 +116,17 @@
     } else {
       appMenus = []
     }
+  } else {
+    menulist = sessionStorage.getItem('fstMenuList')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch (e) {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
   }
   if (appType === 'mob') {
     opentypes = opentypes.filter(item => ['pop', 'prompt', 'exec', 'innerpage', 'funcbutton'].includes(item.value))
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 550fc4f..d7b3e7d 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -171,17 +171,6 @@
       functip = ''
     }
 
-    let menulist = sessionStorage.getItem('fstMenuList')
-    if (menulist) {
-      try {
-        menulist = JSON.parse(menulist)
-      } catch (e) {
-        menulist = []
-      }
-    } else {
-      menulist = []
-    }
-
     let supId = ''
     if (config.setting && config.setting.supModule) {
       let pid = config.setting.supModule[config.setting.supModule.length - 1]
@@ -198,7 +187,7 @@
     this.setState({
       visible: true,
       card: card,
-      formlist: getActionForm(card, functip, config, usefulFields, menulist, modules, anchors)
+      formlist: getActionForm(card, functip, config, usefulFields, modules, anchors)
     })
   }
 
@@ -293,15 +282,10 @@
 
         _actionlist = _actionlist.filter(item => item.uuid !== card.uuid)
 
-        let btnlog = config.btnlog || []
-        if (card.OpenType === 'popview' || card.verify || card.modal) {
-          btnlog.push(card)
-        }
-
         _this.setState({
           actionlist: _actionlist
         }, () => {
-          _this.props.updateaction({...config, action: _actionlist, btnlog})
+          _this.props.updateaction({...config, action: _actionlist})
         })
 
         if (card.origin || appType === 'mob') return
diff --git a/src/menu/components/share/logcomponent/index.jsx b/src/menu/components/share/logcomponent/index.jsx
deleted file mode 100644
index 8130e93..0000000
--- a/src/menu/components/share/logcomponent/index.jsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { Modal, Button, Popconfirm, Table } from 'antd'
-import { RedoOutlined, CloseOutlined, RollbackOutlined } from '@ant-design/icons'
-
-import zhCN from '@/locales/zh-CN/model.js'
-import enUS from '@/locales/en-US/model.js'
-import MKEmitter from '@/utils/events.js'
-import './index.scss'
-
-const { confirm } = Modal
-
-class DataSource extends Component {
-  static propTpyes = {
-    btnlog: PropTypes.array,
-    handlelog: PropTypes.func
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    appType: sessionStorage.getItem('appType'),
-    visible: false,
-    data: [],
-    columns: [
-      {
-        title: '鎸夐挳鍚嶇О',
-        dataIndex: 'label',
-        width: '40%'
-      },
-      {
-        title: '鎸夐挳绫诲瀷',
-        dataIndex: 'OpenType',
-        width: '40%'
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '20%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          (<div style={{textAlign: 'center'}}>
-            <Popconfirm
-              overlayClassName="popover-confirm"
-              title="纭畾鎭㈠璁板綍鍚楋紵"
-              onConfirm={() => this.revert(record)}
-            >
-              <span title="鎭㈠" style={{color: '#26C281', fontSize: '16px', marginRight: '5px', cursor: 'pointer', padding: '5px'}}><RedoOutlined /></span>
-            </Popconfirm>
-            <Popconfirm
-              overlayClassName="popover-confirm"
-              title="纭畾娓呴櫎璁板綍鍚楋紵"
-              onConfirm={() => this.handleDelete(record)}
-            >
-              <span title="娓呴櫎" style={{color: '#ff4d4f', fontSize: '16px', cursor: 'pointer', padding: '5px'}}><CloseOutlined /></span>
-            </Popconfirm>
-          </div>)
-      }
-    ],
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  trigger = () => {
-    this.setState({
-      visible: true,
-      data: fromJS(this.props.btnlog).toJS()
-    })
-  }
-
-  revert = (item) => {
-    const { appType } = this.state
-    const data = this.state.data.filter(d => d.uuid !== item.uuid)
-
-    this.setState({data})
-    this.props.handlelog('revert', data, item)
-
-    if (appType === 'mob' || (appType === 'pc' && item.OpenType !== 'popview')) return
-
-    MKEmitter.emit('thawButtons', item.uuid)
-  }
-
-  handleDelete = (item) => {
-    if (item) {
-      const data = this.state.data.filter(d => d.uuid !== item.uuid)
-  
-      this.setState({data})
-      this.props.handlelog('delete', data, null)
-    } else {
-      const _this = this
-
-      confirm({
-        content: '纭畾娓呯┖璁板綍鍚楋紵',
-        onOk() {
-          _this.setState({data: []})
-          _this.props.handlelog('delete', [], null)
-        },
-        onCancel() {}
-      })
-    }
-  }
-
-  render () {
-    const { btnlog } = this.props
-    const { visible, dict, data, columns } = this.state
-
-    return (
-      <div className={'btn-log-wrap' + (btnlog && btnlog.length > 0 ? ' tip-sign' : '')}>
-        <RollbackOutlined title="瑙i櫎鍐荤粨" onClick={this.trigger} />
-        <Modal
-          wrapClassName="popview-modal"
-          title="鍘嗗彶璁板綍"
-          visible={visible}
-          width={700}
-          maskClosable={false}
-          onCancel={() => { this.setState({ visible: false }) }}
-          footer={[
-            <Button key="close" onClick={() => { this.setState({ visible: false }) }}>{dict['model.close']}</Button>
-          ]}
-          destroyOnClose
-        >
-          <Button disabled={data.length === 0} style={{float: 'right', marginBottom: '5px', position: 'relative', zIndex: 1}} onClick={() => this.handleDelete()} type="primary">娓呯┖</Button>
-          <Table bordered rowKey="uuid" dataSource={data} columns={columns} pagination={false}/>
-        </Modal>
-      </div>
-    )
-  }
-}
-
-export default DataSource
\ No newline at end of file
diff --git a/src/menu/components/share/logcomponent/index.scss b/src/menu/components/share/logcomponent/index.scss
deleted file mode 100644
index 9c974d2..0000000
--- a/src/menu/components/share/logcomponent/index.scss
+++ /dev/null
@@ -1,33 +0,0 @@
-.btn-log-wrap {
-  position: relative;
-  display: inline-block;
-
-  >.anticon-rollback {
-    color: purple;
-  }
-  .operation {
-    text-align: center;
-    .revert {
-      color: #26C281;
-      margin-right: 10px;
-      cursor: pointer;
-      padding: 5px;
-    }
-    .close {
-      color: #ff4d4f;
-      cursor: pointer;
-      padding: 5px;
-    }
-  }
-}
-.btn-log-wrap.tip-sign::after {
-  content: ' ';
-  position: absolute;
-  top: -2px;
-  right: 2px;
-  height: 8px;
-  width: 8px;
-  border-radius: 100%;
-  background: #ff5b05;
-  z-index: 1;
-}
\ No newline at end of file
diff --git a/src/menu/components/share/sourcecomponent/inputform/index.jsx b/src/menu/components/share/sourcecomponent/inputform/index.jsx
index 729dda2..7652431 100644
--- a/src/menu/components/share/sourcecomponent/inputform/index.jsx
+++ b/src/menu/components/share/sourcecomponent/inputform/index.jsx
@@ -18,9 +18,7 @@
 
 class PopSource extends Component {
   static propTpyes = {
-    btnlog: PropTypes.array,
-    keyword: PropTypes.string,
-    handlelog: PropTypes.func
+    keyword: PropTypes.string
   }
 
   state = {
diff --git a/src/menu/components/share/usercomponent/index.jsx b/src/menu/components/share/usercomponent/index.jsx
index c8d4d93..429e0a8 100644
--- a/src/menu/components/share/usercomponent/index.jsx
+++ b/src/menu/components/share/usercomponent/index.jsx
@@ -16,7 +16,7 @@
 
 class UserComponent extends Component {
   static propTpyes = {
-    btnlog: PropTypes.array
+    config: PropTypes.object
   }
 
   state = {
diff --git a/src/menu/components/table/base-table/index.jsx b/src/menu/components/table/base-table/index.jsx
index c4ed949..a99bb1c 100644
--- a/src/menu/components/table/base-table/index.jsx
+++ b/src/menu/components/table/base-table/index.jsx
@@ -71,7 +71,6 @@
           { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
         ],
         scripts: [],
-        btnlog: [],
         isNew: true
       }
 
@@ -193,14 +192,9 @@
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       card.errors = []
 
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
       let doubleClick = card.wrap.doubleClick || ''
   
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
   
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -218,14 +212,6 @@
         if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
           if (!cell.modal || cell.modal.fields.length === 0) {
             card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          // } else {
-          //   cell.modal.fields.forEach(m => {
-          //     if (m.type === 'linkMain' && !supModule) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-          //     }
-          //   })
           }
         }
         if (doubleClick === cell.uuid) {
@@ -239,14 +225,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
             if (doubleClick === cell.uuid) {
@@ -399,44 +377,6 @@
     this.updateComponent(card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.cols.forEach(col => {
-  //         if (col.type !== 'action') return
-  //         if (item.$parentId === col.uuid) {
-  //           col.elements = col.elements ? [...col.elements, item] : [item]
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     if (!done) {
-  //       card.action = card.action ? [...card.action, item] : [item]
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   getWrapForms = () => {
     const { wrap, action, columns, cols } = this.state.card
 
@@ -493,7 +433,6 @@
             <CopyComponent type="normaltable" card={card}/>
             <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent} />
diff --git a/src/menu/components/table/edit-table/columns/index.scss b/src/menu/components/table/edit-table/columns/index.scss
index 3426cb2..6ca33c7 100644
--- a/src/menu/components/table/edit-table/columns/index.scss
+++ b/src/menu/components/table/edit-table/columns/index.scss
@@ -75,12 +75,6 @@
     }
   }
 
-  .model-menu-card-cell-list {
-    .card-detail-row {
-      min-height: 21px;
-    }
-  }
-
   .ant-table-thead {
     th {
       position: relative;
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 3f1c391..69d1200 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -196,6 +196,17 @@
   }
 
   componentDidMount () {
+    this.getsysScript()
+  }
+
+  getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+    
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -214,13 +225,17 @@
     
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
+        let _scripts = res.data.map(item => {
+          return {
+            name: item.funcname,
+            value: window.decodeURIComponent(window.atob(item.longparam))
+          }
+        })
+
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
         this.setState({
-          systemScripts: res.data.map(item => {
-            return {
-              name: item.funcname,
-              value: window.decodeURIComponent(window.atob(item.longparam))
-            }
-          })
+          systemScripts: _scripts
         })
       } else {
         notification.warning({
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index f1c9345..f74ba6b 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 import Utils from '@/utils/utils.js'
@@ -68,7 +68,6 @@
           { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
         ],
         scripts: [],
-        btnlog: [],
         submit: {intertype: 'system', default: 'true', innerFunc: '', execSuccess: 'grid', execError: 'never', scripts: [], uniques: []},
         isNew: true
       }
@@ -167,14 +166,8 @@
 
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       card.errors = []
-  
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
-  
+
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
 
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -187,19 +180,15 @@
       } else if (!card.setting.supModule) {
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
+
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
   
       card.action.forEach(cell => {
         if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
           if (!cell.modal || cell.modal.fields.length === 0) {
             card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          // } else {
-          //   cell.modal.fields.forEach(m => {
-          //     if (m.type === 'linkMain' && !supModule) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-          //     }
-          //   })
           }
         }
       })
@@ -210,14 +199,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
           })
diff --git a/src/menu/components/table/normal-table/columns/index.scss b/src/menu/components/table/normal-table/columns/index.scss
index 9e88629..db07412 100644
--- a/src/menu/components/table/normal-table/columns/index.scss
+++ b/src/menu/components/table/normal-table/columns/index.scss
@@ -65,11 +65,6 @@
       background: #ffffff!important;
     }
   }
-  .model-menu-card-cell-list {
-    .card-detail-row {
-      min-height: 21px;
-    }
-  }
 
   .ant-table-thead {
     th {
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index a2448ee..0983391 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 import Utils from '@/utils/utils.js'
@@ -22,7 +22,6 @@
 const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const ClockComponent = asyncIconComponent(() => import('@/menu/components/share/clockcomponent'))
-// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
 const ColumnComponent = asyncComponent(() => import('./columns'))
 
 class TableCardEditComponent extends Component {
@@ -75,7 +74,6 @@
           { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
         ],
         scripts: [],
-        btnlog: [],
         isNew: true
       }
 
@@ -145,7 +143,6 @@
 
   componentDidMount () {
     MKEmitter.addListener('submitModal', this.handleSave)
-    // MKEmitter.addListener('logButton', this.logButton)
     MKEmitter.addListener('completeSave', this.completeSave)
   }
 
@@ -161,7 +158,6 @@
       return
     }
     MKEmitter.removeListener('submitModal', this.handleSave)
-    // MKEmitter.removeListener('logButton', this.logButton)
     MKEmitter.removeListener('completeSave', this.completeSave)
   }
 
@@ -207,14 +203,9 @@
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       card.errors = []
 
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
       let doubleClick = card.wrap.doubleClick || ''
   
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
   
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -228,18 +219,14 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.action.forEach(cell => {
         if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
           if (!cell.modal || cell.modal.fields.length === 0) {
             card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          // } else {
-          //   cell.modal.fields.forEach(m => {
-          //     if (m.type === 'linkMain' && !supModule) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-          //     }
-          //   })
           }
         }
         if (doubleClick === cell.uuid) {
@@ -253,14 +240,6 @@
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
             if (doubleClick === cell.uuid) {
@@ -298,17 +277,6 @@
     
     this.props.updateConfig(_card)
   }
-
-  // logButton = (id, item) => {
-  //   const { card } = this.state
-
-  //   if (id !== card.uuid) return
-
-  //   let btnlog = card.btnlog || []
-  //   btnlog.push(item)
-
-  //   this.updateComponent({...card, btnlog})
-  // }
 
   changeStyle = () => {
     const { card } = this.state
@@ -424,44 +392,6 @@
     this.updateComponent(card)
   }
 
-  // handleLog = (type, logs, item) => {
-  //   let card = fromJS(this.state.card).toJS()
-
-  //   if (type === 'revert') {
-  //     let done = false
-  //     if (item.$parentId) {
-  //       card.cols.forEach(col => {
-  //         if (col.type !== 'action') return
-  //         if (item.$parentId === col.uuid) {
-  //           col.elements = col.elements ? [...col.elements, item] : [item]
-  //           done = true
-  //         }
-  //       })
-  //     }
-
-  //     if (!done) {
-  //       card.action = card.action ? [...card.action, item] : [item]
-  //     }
-
-  //     card.btnlog = logs
-
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '鎭㈠鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   } else {
-  //     card.btnlog = logs
-  //     this.updateComponent(card)
-  //     notification.success({
-  //       top: 92,
-  //       message: '娓呴櫎鎴愬姛锛�',
-  //       duration: 2
-  //     })
-  //   }
-  // }
-
   getWrapForms = () => {
     const { wrap, action, columns, cols } = this.state.card
 
@@ -522,7 +452,6 @@
             <CopyComponent type="normaltable" card={card}/>
             <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
-            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
             <ClockComponent config={card} updateConfig={this.updateComponent}/>
             <UserComponent config={card}/>
             <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
diff --git a/src/menu/components/timeline/normal-timeline/index.jsx b/src/menu/components/timeline/normal-timeline/index.jsx
index 54da944..be03907 100644
--- a/src/menu/components/timeline/normal-timeline/index.jsx
+++ b/src/menu/components/timeline/normal-timeline/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -115,12 +115,7 @@
     if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
       card.errors = []
 
-      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
-      // if (supModule === 'empty') {
-      //   supModule = ''
-      // }
       let columns = card.columns.map(c => c.field)
-      // let lowcols = card.columns.map(c => c.field.toLowerCase())
   
       if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
         card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
@@ -134,20 +129,16 @@
         card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
       }
 
+      if (card.errors.length === 0) {
+        card.$tables = getTables(card)
+      }
+
       card.subcards.forEach(col => {
         col.elements.forEach(cell => {
           if (cell.eleType === 'button') {
             if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
               if (!cell.modal || cell.modal.fields.length === 0) {
                 card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              // } else {
-              //   cell.modal.fields.forEach(m => {
-              //     if (m.type === 'linkMain' && !supModule) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
-              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
-              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
-              //     }
-              //   })
               }
             }
           } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
diff --git a/src/menu/components/tree/antd-tree/index.jsx b/src/menu/components/tree/antd-tree/index.jsx
index 0c5d16e..529cce9 100644
--- a/src/menu/components/tree/antd-tree/index.jsx
+++ b/src/menu/components/tree/antd-tree/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle } from '@/utils/utils-custom.js'
+import { resetStyle, getTables } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import getWrapForm from './options'
 
@@ -114,6 +114,10 @@
       card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
 
+    if (card.errors.length === 0) {
+      card.$tables = getTables(card)
+    }
+
     if (!card.wrap.parentField || !card.wrap.valueField || !card.wrap.labelField) {
       card.errors.push({ level: 0, detail: '鏈缃熀鏈俊鎭紒'})
     }
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index eb4f54b..e71780a 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -40,6 +40,11 @@
     const { config } = this.props
     const { appType } = this.state
 
+    if (config.type === 'interface') { // 鍏叡鏁版嵁婧愪笉浣跨敤鎼滅储
+      this.setState({visible: true})
+      return
+    }
+
     let search = []
     let menu = fromJS(window.GLOB.customMenu).toJS()
 
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 74152b1..64a38ce 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -202,6 +202,13 @@
   }
 
   getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -220,16 +227,14 @@
     
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
-        let _scripts = []
-
-        res.data.forEach(item => {
-          let _item = {
+        let _scripts = res.data.map(item => {
+          return {
             name: item.funcname,
             value: window.decodeURIComponent(window.atob(item.longparam))
           }
-
-          _scripts.push(_item)
         })
+
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
 
         this.setState({
           systemScripts: _scripts
@@ -738,14 +743,18 @@
               wrappedComponentRef={(inst) => this.settingForm = inst}
             />
           </TabPane>
-          <TabPane tab="瀛楁闆�" key="columns">
+          <TabPane tab={
+            <span>
+              瀛楁闆�
+              <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" className="mk-copy-fields" onClick={this.copyColumns}/>
+            </span>
+          } key="columns">
             <ColForm dict={this.props.dict} columnChange={this.columnChange}/>
             <FieldsComponent
               config={{...config, columns}}
               type="fields"
               updatefield={this.updatefields}
             />
-            <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" onClick={this.copyColumns} style={{position: 'absolute', cursor: 'pointer', zIndex: 1, top: '-35px', right: '0px', color: '#1890ff'}} />
             <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} type="datasourcefield" wrappedComponentRef={(inst) => this.datasource = inst} data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
           </TabPane>
           <TabPane tab={
diff --git a/src/menu/datasource/verifycard/index.scss b/src/menu/datasource/verifycard/index.scss
index 8615405..4be45ad 100644
--- a/src/menu/datasource/verifycard/index.scss
+++ b/src/menu/datasource/verifycard/index.scss
@@ -9,6 +9,18 @@
     .ant-tabs-nav-scroll {
       text-align: center;
     }
+    .mk-copy-fields {
+      position: absolute;
+      cursor: pointer;
+      z-index: 1;
+      top: 19px;
+      right: -210px;
+      color: rgb(24, 144, 255);
+      display: none;
+    }
+    .ant-tabs-tab-active .mk-copy-fields {
+      display: inline-block;
+    }
     .count-tip {
       position: absolute;
       top: 0px;
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index cc9c58e..f0ff0c4 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -1,5 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
 import { Form, Row, Col, Input, Radio, Tooltip, notification, Select, InputNumber, Cascader } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
@@ -22,18 +23,15 @@
   }
 
   state = {
-    interType: this.props.setting.interType || 'system',
-    laypage: this.props.setting.laypage || 'true',
+    setting: null,
     modules: [],
-    usefulFields: [],
-    useMSearch: this.props.setting.useMSearch || 'false',
-    sysInterface: this.props.setting.sysInterface || 'false',
-    supModule: this.props.setting.supModule || [],
+    innerRules: [],
+    innertip: '',
     appType: sessionStorage.getItem('appType')
   }
 
   UNSAFE_componentWillMount () {
-    const { config } = this.props
+    const { config, setting } = this.props
 
     let modules = MenuUtils.getSupModules(window.GLOB.customMenu.components, config.uuid) || []
 
@@ -43,17 +41,36 @@
     })
 
     let usefulFields = sessionStorage.getItem('permFuncField')
+    let innerRules = []
+    let innertip = ''
     if (usefulFields) {
       try {
         usefulFields = JSON.parse(usefulFields)
+
+        if (usefulFields.length > 0) {
+          innertip = '寮�澶村彲鐢ㄥ瓧绗︼細' + usefulFields.join(', ')
+          let str = '^(' + usefulFields.join('|') + ')'
+          let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
+    
+          innerRules.push({
+            pattern: _patten,
+            message: formRule.func.innerMessage
+          })
+        }
       } catch (e) {
-        usefulFields = []
+        innerRules = []
       }
-    } else {
-      usefulFields = []
     }
 
-    this.setState({modules, usefulFields})
+    let _setting = fromJS(setting).toJS()
+    _setting.interType = setting.interType || 'system'
+    _setting.laypage = setting.laypage || 'true'
+    _setting.useMSearch = setting.useMSearch || 'false'
+    _setting.sysInterface = setting.sysInterface || 'false'
+    _setting.supModule = setting.supModule || []
+    _setting.execute = setting.execute || 'true'
+
+    this.setState({modules, innerRules, innertip, setting: _setting})
   }
 
   handleConfirm = () => {
@@ -69,15 +86,7 @@
           }
 
           // 鏁版嵁婧愬墠绔獙璇�
-          if (values.interType === 'system' && values.execute !== 'false' && !values.dataresource) {
-            notification.warning({
-              top: 92,
-              message: '璇峰~鍐欏唴閮ㄥ嚱鏁版垨鏁版嵁婧愶紒',
-              duration: 5
-            })
-            reject()
-            return
-          } else if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
+          if (values.interType === 'system' && values.execute !== 'false' && values.dataresource) {
             let _quot = values.dataresource.match(/'{1}/g)
             let _lparen = values.dataresource.match(/\({1}/g)
             let _rparen = values.dataresource.match(/\){1}/g)
@@ -133,35 +142,21 @@
     })
   }
 
-  onRadioChange = (e, key) => {
-    let value = e.target.value
+  onOptionChange = (value, key) => {
+    let setting = fromJS(this.state.setting).toJS()
+    setting[key] = value
 
-    if (key === 'interType') {
-      this.setState({
-        interType: value
-      })
-    }
-  }
-  
-  onSysInter = (e) => {
-    let value = e.target.value
-    
-    this.setState({
-      sysInterface: value
-    })
-    if (value === 'true') {
+    this.setState({setting})
+
+    if (key === 'sysInterface' && value === 'true') {
       this.props.form.setFieldsValue({interface: window.GLOB.mainSystemApi})
     }
   }
 
-  changeSupModule = (val) => {
-    this.setState({supModule: val})
-  }
-
   render() {
-    const { setting, columns, config } = this.props
+    const { columns, config } = this.props
     const { getFieldDecorator } = this.props.form
-    const { interType, modules, useMSearch, laypage, supModule, usefulFields, appType, sysInterface } = this.state
+    const { setting, modules, innerRules, appType, innertip } = this.state
 
     const formItemLayout = {
       labelCol: {
@@ -174,24 +169,23 @@
       }
     }
 
-    let tooltip = null
-    let rules = []
-
-    if (usefulFields.length > 0) {
-      tooltip = '寮�澶村彲鐢ㄥ瓧绗︼細' + usefulFields.join(', ')
-      let str = '^(' + usefulFields.join('|') + ')'
-      let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-      rules.push({
-        pattern: _patten,
-        message: formRule.func.innerMessage
-      })
-    }
-
     return (
       <div className="model-datasource-setting-form-box">
         <Form {...formItemLayout} className="model-setting-form">
           <Row gutter={24}>
+            {config.type === 'interface' ? <Col span={8}>
+              <Form.Item label="鏁版嵁婧愬悕绉�">
+                {getFieldDecorator('name', {
+                  initialValue: setting.name,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '鏁版嵁婧愬悕绉�!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" />)}
+              </Form.Item>
+            </Col> : null}
             <Col span={8}>
               <Form.Item label="琛ㄥ悕">
                 {getFieldDecorator('tableName', {
@@ -204,6 +198,10 @@
                     {
                       max: 50,
                       message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!'
+                    },
+                    {
+                      pattern: /^[a-zA-Z_]+$/,
+                      message: '琛ㄥ悕鍙彲浣跨敤瀛楁瘝浠ュ強_'
                     }
                   ]
                 })(<Input placeholder={''} autoComplete="off" />)}
@@ -212,7 +210,7 @@
             <Col span={8}>
               <Form.Item label="鎺ュ彛绫诲瀷">
                 {getFieldDecorator('interType', {
-                  initialValue: interType,
+                  initialValue: setting.interType,
                   rules: [
                     {
                       required: true,
@@ -220,17 +218,17 @@
                     },
                   ]
                 })(
-                <Radio.Group onChange={(e) => {this.onRadioChange(e, 'interType')}}>
+                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'interType')}}>
                   <Radio value="system">绯荤粺</Radio>
                   <Radio value="inner">鍐呴儴</Radio>
                   <Radio value="outer">澶栭儴</Radio>
                 </Radio.Group>)}
               </Form.Item>
             </Col>
-            {interType === 'outer' ? <Col span={8}>
+            {setting.interType === 'outer' ? <Col span={8}>
               <Form.Item label="绯荤粺鎺ュ彛">
                 {getFieldDecorator('sysInterface', {
-                  initialValue: sysInterface,
+                  initialValue: setting.sysInterface,
                   rules: [
                     {
                       required: true,
@@ -238,15 +236,15 @@
                     }
                   ]
                 })(
-                <Radio.Group onChange={this.onSysInter}>
+                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'sysInterface')}}>
                   <Radio value="true">鏄�</Radio>
                   <Radio value="false">鍚�</Radio>
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {interType === 'inner' ? <Col span={8}>
-              <Form.Item label={tooltip ?
-                <Tooltip placement="topLeft" title={tooltip}>
+            {setting.interType === 'inner' ? <Col span={8}>
+              <Form.Item label={innertip ?
+                <Tooltip placement="topLeft" title={innertip}>
                   <QuestionCircleOutlined className="mk-form-tip" />
                   鍐呴儴鍑芥暟
                 </Tooltip> : '鍐呴儴鍑芥暟'
@@ -258,25 +256,25 @@
                       required: true,
                       message: this.props.dict['form.required.input'] + '鍐呴儴鍑芥暟!'
                     },
-                    ...rules
+                    ...innerRules
                   ]
                 })(<Input placeholder={''} autoComplete="off" />)}
               </Form.Item>
             </Col> : null}
-            {interType === 'outer' ? <Col className="outer-interface" span={24}>
+            {setting.interType === 'outer' ? <Col className="outer-interface" span={24}>
               <Form.Item label="鎺ュ彛鍦板潃">
                 {getFieldDecorator('interface', {
-                  initialValue: setting.interface || (sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
+                  initialValue: setting.interface || (setting.sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
                   rules: [
                     {
-                      required: sysInterface !== 'true' ? true : false,
+                      required: setting.sysInterface !== 'true' ? true : false,
                       message: this.props.dict['form.required.input'] + '鎺ュ彛鍦板潃!'
                     }
                   ]
-                })(<TextArea rows={2} readOnly={sysInterface === 'true'}/>)}
+                })(<TextArea rows={2} readOnly={setting.sysInterface === 'true'}/>)}
               </Form.Item>
             </Col> : null}
-            {interType === 'outer' && sysInterface !== 'true' ? <Col className="outer-interface" span={24}>
+            {setting.interType === 'outer' && setting.sysInterface !== 'true' ? <Col className="outer-interface" span={24}>
               <Form.Item label={<Tooltip placement="topLeft" title="姝e紡绯荤粺鎺ュ彛鍦板潃锛屼负绌烘椂浣跨敤鎺ュ彛鍦板潃">
                   <QuestionCircleOutlined className="mk-form-tip" />
                   姝e紡鍦板潃
@@ -287,17 +285,14 @@
                 })(<TextArea rows={2}/>)}
               </Form.Item>
             </Col> : null}
-            {interType === 'outer' ? <Col span={8}>
+            {setting.interType === 'outer' ? <Col span={8}>
               <Form.Item label="澶栭儴鍑芥暟">
                 {getFieldDecorator('outerFunc', {
-                  initialValue: setting.outerFunc || '',
-                  rules: [
-
-                  ]
+                  initialValue: setting.outerFunc || ''
                 })(<Input placeholder={''} autoComplete="off" />)}
               </Form.Item>
             </Col> : null}
-            {interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
+            {setting.interType === 'system' ? <Col span={24} className="data-source" style={{paddingLeft: '7px'}}>
               <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 2 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 22 }} } label={
                 <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -305,11 +300,17 @@
                 </Tooltip>
               }>
                 {getFieldDecorator('dataresource', {
-                  initialValue: setting.dataresource || ''
+                  initialValue: setting.dataresource || '',
+                  rules: [
+                    {
+                      required: setting.execute !== 'false' ? true : false,
+                      message: this.props.dict['form.required.input'] + '鏁版嵁婧�!'
+                    }
+                  ]
                 })(<CodeMirror />)}
               </Form.Item>
             </Col> : null}
-            {interType === 'system' ? <Col span={8}>
+            {setting.interType === 'system' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'鏌ヨ鏃讹紝鎼滅储鏉′欢浠here鏉′欢鎷兼帴杩涘叆sql锛岀粺璁℃椂锛屽皢鏁版嵁婧愪腑浠モ�淍+鎼滅储瀛楁+@鈥濈殑鍐呭锛屼互鎼滅储鏉′欢涓殑鍊艰繘琛屾浛鎹㈠悗锛屾彁浜ゆ煡璇紝娉細鏌ヨ绫诲瀷浠呭湪浣跨敤绯荤粺鍑芥暟鏃舵湁鏁堛��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -354,18 +355,18 @@
                 })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
               </Form.Item>
             </Col> : null}
-            {interType === 'system' ? <Col span={8}>
+            {setting.interType === 'system' ? <Col span={8}>
               <Form.Item label="榛樿sql">
                 {getFieldDecorator('execute', {
-                  initialValue: setting.execute || 'true'
+                  initialValue: setting.execute
                 })(
-                <Radio.Group>
+                <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'execute')}}>
                   <Radio value="true">鎵ц</Radio>
                   <Radio value="false">涓嶆墽琛�</Radio>
                 </Radio.Group>)}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) && (!config.wrap || config.wrap.supType !== 'multi') ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'璇ョ粍浠跺鏋滃彈鍏朵粬缁勪欢鎺у埗锛岃閫夐」鐩稿簲鐨勭粍浠讹紝娌℃湁鏃堕�夆�滄棤鈥濄��'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -373,7 +374,7 @@
                 </Tooltip>
               }>
                 {getFieldDecorator('supModule', {
-                  initialValue: supModule,
+                  initialValue: setting.supModule,
                   rules: [
                     {
                       required: true,
@@ -381,7 +382,7 @@
                     }
                   ]
                 })(
-                  <Cascader options={modules} onChange={this.changeSupModule} expandTrigger="hover" placeholder="" />
+                  <Cascader options={modules} onChange={(val) => {this.onOptionChange(val, 'supModule')}} expandTrigger="hover" placeholder="" />
                 )}
               </Form.Item>
             </Col> : null}
@@ -390,14 +391,14 @@
                 {getFieldDecorator('laypage', {
                   initialValue: setting.laypage || 'true'
                 })(
-                  <Radio.Group onChange={(e) => this.setState({laypage: e.target.value})}>
+                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'laypage')}}>
                     <Radio value="true">鏄�</Radio>
                     <Radio value="false">鍚�</Radio>
                   </Radio.Group>
                 )}
               </Form.Item>
             </Col> : null}
-            {config.pageable && laypage !== 'false' ? <Col span={8}>
+            {config.pageable && setting.laypage !== 'false' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title="閫夋嫨鍒嗛〉鏃舵湁鏁堛��">
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -416,7 +417,7 @@
               </Form.Item>
             </Col> : null}
             {/* 1銆佷笉鍒嗛〉涓斾笉瀛樺湪涓婄骇妯″潡 */}
-            {!['navbar'].includes(config.type) && !['editable'].includes(config.subtype) && (!config.pageable || (config.pageable && laypage === 'false')) && (!supModule || supModule.length === 0 || supModule[0] === 'empty') ? <Col span={8}>
+            {!['navbar', 'interface'].includes(config.type) && !['editable'].includes(config.subtype) && (!config.pageable || (config.pageable && setting.laypage === 'false')) && (setting.supModule.length === 0 || setting.supModule[0] === 'empty') ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'鍒濆鍖栧姞杞芥椂锛屾槸鍚︿笌鍏朵粬缁勪欢涓�鍚屽姞杞芥暟鎹紝娉細浠呭湪浣跨敤绯荤粺鍑芥暟锛屼笖鍒濆鍖栧姞杞芥暟鎹椂鏈夋晥锛屽垎椤佃姹傛椂鏃犳晥銆�'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -433,7 +434,7 @@
                 )}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'浼樺厛浣跨敤鍚岀骇鐨勬悳绱㈡潯浠剁粍浠讹紝鍚岀骇鎼滅储涓嶅瓨鍦ㄦ椂锛屼緷娆″悜涓婇�夊彇锛屼笌褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵竴鍚岀敤浣滄暟鎹繃婊わ紙褰撳墠缁勪欢鐨勬悳绱㈡潯浠朵紭鍏堬級銆�'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -443,14 +444,14 @@
                 {getFieldDecorator('useMSearch', {
                   initialValue: setting.useMSearch || 'true'
                 })(
-                  <Radio.Group onChange={(e) => this.setState({useMSearch: e.target.value})}>
+                  <Radio.Group onChange={(e) => {this.onOptionChange(e.target.value, 'useMSearch')}}>
                     <Radio value="true">浣跨敤</Radio>
                     <Radio value="false">涓嶄娇鐢�</Radio>
                   </Radio.Group>
                 )}
               </Form.Item>
             </Col> : null}
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) && useMSearch === 'true' && appType !== 'mob' ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) && setting.useMSearch === 'true' && appType !== 'mob' ? <Col span={8}>
               <Form.Item label={
                 <Tooltip placement="topLeft" title={'澶栧眰鎼滅储鏉′欢鏀瑰彉鏃讹紝鏄惁鍒锋柊褰撳墠缁勪欢鏁版嵁銆�'}>
                   <QuestionCircleOutlined className="mk-form-tip" />
@@ -478,7 +479,7 @@
                 </Radio.Group>)}
               </Form.Item>
             </Col>
-            {!['navbar', 'balcony', 'menubar'].includes(config.type) ? <Col span={8}>
+            {!['navbar', 'balcony', 'menubar', 'interface'].includes(config.type) ? <Col span={8}>
               <Form.Item label="鍒濆鍖栨暟鎹�">
                 {getFieldDecorator('onload', {
                   initialValue: setting.onload || 'true'
@@ -490,6 +491,39 @@
                 )}
               </Form.Item>
             </Col> : null}
+            {config.type === 'interface' ? <Col span={8}>
+              <Form.Item label="瀹氭椂鍣�">
+                {getFieldDecorator('timer', {
+                  initialValue: setting.timer || ''
+                })(
+                  <Select onChange={(value) => {this.onOptionChange(value, 'timer')}}>
+                    <Select.Option value=""> 鏃� </Select.Option>
+                    <Select.Option value="2s"> 2绉� </Select.Option>
+                    <Select.Option value="5s"> 5绉� </Select.Option>
+                    <Select.Option value="15s"> 15绉� </Select.Option>
+                    <Select.Option value="30s"> 30绉� </Select.Option>
+                    <Select.Option value="1min"> 1鍒嗛挓 </Select.Option>
+                    <Select.Option value="5min"> 5鍒嗛挓 </Select.Option>
+                    <Select.Option value="10min"> 10鍒嗛挓 </Select.Option>
+                    <Select.Option value="15min"> 15鍒嗛挓 </Select.Option>
+                    <Select.Option value="30min"> 30鍒嗛挓 </Select.Option>
+                    <Select.Option value="1hour"> 1灏忔椂 </Select.Option>
+                  </Select>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {config.type === 'interface' && setting.timer ? <Col span={8}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="瀹氭椂鍣ㄦ墽琛屾鏁般�傛敞锛�0琛ㄧず娌℃湁闄愬埗銆�">
+                  <QuestionCircleOutlined className="mk-form-tip" />
+                  鎵ц娆℃暟
+                </Tooltip>
+              }>
+                {getFieldDecorator('timerRepeats', {
+                  initialValue: setting.timerRepeats || 0
+                })(<InputNumber min={0} max={500} precision={0} />)}
+              </Form.Item>
+            </Col> : null}
           </Row>
         </Form>
       </div>
diff --git a/src/menu/datasource/verifycard/utils.jsx b/src/menu/datasource/verifycard/utils.jsx
index 38cfddf..835d503 100644
--- a/src/menu/datasource/verifycard/utils.jsx
+++ b/src/menu/datasource/verifycard/utils.jsx
@@ -221,7 +221,7 @@
         }
         scripts && scripts.forEach(script => {
           if (reg.test(script.sql)) {
-            errors.push(`鑷畾涔夎剼鏈�(${script.$index})瀛樺湪鏈浛鎹㈠��${item}`)
+            errors.push(`鑷畾涔夎剼鏈�(${script.$index || ''})瀛樺湪鏈浛鎹㈠��${item}`)
           }
         })
       })
diff --git a/src/menu/sysinterface/index.jsx b/src/menu/sysinterface/index.jsx
index e221366..c24c4b0 100644
--- a/src/menu/sysinterface/index.jsx
+++ b/src/menu/sysinterface/index.jsx
@@ -1,14 +1,15 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Modal, Button, Popconfirm, message } from 'antd'
-import { StopTwoTone, ApiOutlined, CopyOutlined, EditOutlined, CheckCircleTwoTone, DeleteOutlined } from '@ant-design/icons'
+import { Modal, Button, Popconfirm, message, notification } from 'antd'
+import { StopTwoTone, DatabaseOutlined, CopyOutlined, CheckCircleTwoTone, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
 import asyncComponent from '@/utils/asyncComponent'
+import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
-const SettingForm = asyncComponent(() => import('./settingform'))
+const DataSource = asyncComponent(() => import('@/menu/datasource'))
 const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
 
 class InterfaceController extends Component {
@@ -19,12 +20,10 @@
 
   state = {
     visible: false,
-    setvisible: false,
     interfaces: [],
-    card: null,
     columns: [
       {
-        title: '鎺ュ彛鍚嶇О',
+        title: '鍚嶇О',
         dataIndex: 'name',
         width: '50%'
       },
@@ -53,8 +52,9 @@
         dataIndex: 'operation',
         render: (text, record) =>
           (<div style={{textAlign: 'center'}}>
-            <span onClick={() => this.handleEdit(record)} style={{color: '#1890ff', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><EditOutlined /></span>
-            <span onClick={() => {this.copy(record)}} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
+            <DataSource config={record} updateConfig={this.update}/>
+            <span onClick={() => this.handleStatus(record)} style={{color: '#8E44AD', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><SwapOutlined /></span>
+            <span onClick={() => this.copy(record)} style={{color: '#26C281', cursor: 'pointer', fontSize: '16px', marginRight: '15px'}}><CopyOutlined /></span>
             <Popconfirm
               overlayClassName="popover-confirm"
               title="纭畾鍒犻櫎锛�"
@@ -107,8 +107,46 @@
     })
   }
 
-  handleEdit = (record) => {
-    this.setState({card: record, setvisible: true})
+  handleStatus = (record) => {
+    const { config } = this.props
+    
+    if (record.status === 'false') {
+      if (record.setting.interType === 'system' && record.setting.execute !== 'false' && !record.setting.dataresource) {
+        notification.warning({
+          top: 92,
+          message: '鏈缃暟鎹簮锛屼笉鍙惎鐢紒',
+          duration: 5
+        })
+        return
+      } else if (!record.setting.primaryKey) {
+        notification.warning({
+          top: 92,
+          message: '鏈缃富閿紝涓嶅彲鍚敤锛�',
+          duration: 5
+        })
+        return
+      } else if (record.columns.length === 0) {
+        notification.warning({
+          top: 92,
+          message: '鏈坊鍔犲瓧娈甸泦锛屼笉鍙惎鐢紒',
+          duration: 5
+        })
+        return
+      }
+    }
+
+    record = fromJS(record).toJS()
+    record.status = record.status === 'false' ? 'true' : 'false'
+
+    let interfaces = this.state.interfaces.map(item => {
+      if (item.uuid !== record.uuid) {
+        return item
+      }
+      return record
+    })
+
+    this.setState({ interfaces })
+    this.props.updateConfig({...config, interfaces})
   }
 
   deleteScript = (record) => {
@@ -126,37 +164,30 @@
     this.props.updateConfig({...config, interfaces})
   }
 
-  settingSave = () => {
+  update = (record) => {
     const { config } = this.props
-    const { card } = this.state
-    let interfaces = fromJS(this.state.interfaces).toJS()
 
-    this.settingRef.handleConfirm().then(res => {
-      interfaces = interfaces.map(item => {
-        if (item.uuid === card.uuid) {
-          res.uuid = item.uuid
+    if (record.setting.primaryKey && record.columns.length > 0) {
+      record.status = 'true'
+    } else if (record.columns.length === 0) {
+      record.status = 'false'
+    }
+    record.name = record.setting.name
 
-          if (res.procMode !== 'inner' && res.preScripts && res.preScripts.filter(item => item.status !== 'false').length === 0) {
-            message.warning('鏈缃墠缃剼鏈紝涓嶅彲鍚敤锛�')
-            res.status = 'false'
-          } else if (res.callbackType === 'script' && res.cbScripts && res.cbScripts.filter(item => item.status !== 'false').length === 0) {
-            message.warning('鏈缃洖璋冭剼鏈紝涓嶅彲鍚敤锛�')
-            res.status = 'false'
-          }
-
-          return res
-        }
+    let interfaces = this.state.interfaces.map(item => {
+      if (item.uuid !== record.uuid) {
         return item
-      })
-
-      this.setState({
-        card: null,
-        setvisible: false,
-        interfaces
-      })
-
-      this.props.updateConfig({...config, interfaces})
+      }
+      return record
     })
+
+    
+    this.setState({ interfaces })
+    this.props.updateConfig({...config, interfaces})
+
+    setTimeout(() => {
+      MKEmitter.emit('mkUpdateInter', record, {delay: 0})
+    }, 10)
   }
 
   addInterface = () => {
@@ -165,11 +196,14 @@
 
     interfaces.push({
       uuid: Utils.getuuid(),
-      name: 'interface ' + (interfaces.length + 1),
-      procMode: 'script',
-      callbackType: 'script',
-      preScripts: [],
-      cbScripts: []
+      name: '鏁版嵁婧�' + (interfaces.length + 1),
+      status: 'false',
+      format: 'array',
+      type: 'interface',
+      pageable: false,
+      setting: { interType: 'system', name: '鏁版嵁婧�' + (interfaces.length + 1), status: 'false' },
+      columns: [],
+      scripts: [],
     })
 
     this.setState({
@@ -179,13 +213,13 @@
   }
 
   render() {
-    const { visible, setvisible, columns, interfaces, card } = this.state
+    const { visible, columns, interfaces } = this.state
 
     return (
       <div className="mk-sys-interface" style={{display: 'inline-block'}}>
-        <Button className="mk-border-green" onClick={this.trigger}><ApiOutlined /> 鎺ュ彛绠$悊</Button>
+        <Button className="mk-border-green" onClick={this.trigger}><DatabaseOutlined /> 鍏叡鏁版嵁婧�</Button>
         <Modal
-          title="鎺ュ彛绠$悊"
+          title="鍏叡鏁版嵁婧�"
           wrapClassName="interface-controller-modal"
           visible={visible}
           width={800}
@@ -198,21 +232,9 @@
           ]}
           destroyOnClose
         > 
-          <Button key="add-interface" className="mk-border-green" onClick={this.addInterface}> 娣诲姞 </Button>
+          <PlusOutlined key="add-interface" onClick={this.addInterface}/>
           {/* <div style={{fontSize: '12px', position: 'relative', top: '20px'}}>娉細鎺ュ彛鎵ц瀹屾垚鍚庯紝浼氳Е鍙戦粯璁や笉鍔犺浇鐨勭粍浠跺埛鏂版暟鎹��</div> */}
-          <EditTable key="manage-interface" actions={['move', 'copy']} type="interface" data={interfaces} columns={columns} onChange={this.changeScripts}/>
-        </Modal>
-        <Modal
-          title={card ? card.name : '鎺ュ彛'}
-          wrapClassName="interface-edit-modal"
-          visible={setvisible}
-          width={900}
-          maskClosable={false}
-          onOk={this.settingSave}
-          onCancel={() => { this.setState({ setvisible: false })}}
-          destroyOnClose
-        >
-          <SettingForm config={card} wrappedComponentRef={(inst) => this.settingRef = inst}/>
+          <EditTable key="manage-interface" actions={['copy']} type="interface" data={interfaces} columns={columns} onChange={this.changeScripts}/>
         </Modal>
       </div>
     )
diff --git a/src/menu/sysinterface/index.scss b/src/menu/sysinterface/index.scss
index c4d74b5..50b4f4d 100644
--- a/src/menu/sysinterface/index.scss
+++ b/src/menu/sysinterface/index.scss
@@ -1,20 +1,22 @@
 .interface-controller-modal {
-  >.ant-modal >.ant-modal-content >.ant-modal-body {
+  .ant-modal-body {
     min-height: 400px;
-    >.mk-border-green {
+    >.anticon-plus {
       float: right;
       position: relative;
       z-index: 1;
-      margin-bottom: 10px;
+      margin: 0px 10px 10px;
+      font-size: 20px;
+      color: #26C281;
+    }
+    .model-datasource {
+      position: relative;
+      top: 0;
+      color: #1890ff;
+      display: inline-block;
+      > .anticon-setting {
+        font-size: 16px;
+      }
     }
   }
 }
-.interface-edit-modal {
-  .ant-modal {
-    top: 70px;
-  }
-  .ant-modal-body {
-    min-height: 300px;
-    padding-top: 5px;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/baseform/index.jsx b/src/menu/sysinterface/settingform/baseform/index.jsx
deleted file mode 100644
index ea3b695..0000000
--- a/src/menu/sysinterface/settingform/baseform/index.jsx
+++ /dev/null
@@ -1,260 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Tooltip } from 'antd'
-import { QuestionCircleOutlined } from '@ant-design/icons'
-
-import { formRule } from '@/utils/option.js'
-import './index.scss'
-
-const { TextArea } = Input
-
-class SettingForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object,       // 瀛楀吀椤�
-    setting: PropTypes.object,    // 鏁版嵁婧愰厤缃�
-    updateStatus: PropTypes.func, // 鐘舵�佹洿鏂�
-  }
-
-  state = {
-    procMode: 'script',
-    funcTooltip: '',
-    funcRules: []
-  }
-
-  UNSAFE_componentWillMount () {
-    const { setting } = this.props
-
-    let usefulFields = sessionStorage.getItem('permFuncField')
-    if (usefulFields) {
-      try {
-        usefulFields = JSON.parse(usefulFields)
-      } catch (e) {
-        usefulFields = []
-      }
-    } else {
-      usefulFields = []
-    }
-    
-    let tooltip = null
-    let rules = []
-
-    if (usefulFields.length > 0) {
-      tooltip = '寮�澶村彲鐢ㄥ瓧绗︼細' + usefulFields.join(', ')
-      let str = '^(' + usefulFields.join('|') + ')'
-      let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-      rules.push({
-        pattern: _patten,
-        message: formRule.func.innerMessage
-      })
-    }
-
-    this.setState({
-      procMode: setting.procMode || 'script',
-      funcTooltip: tooltip,
-      funcRules: rules
-    })
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          resolve(values)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  onRadioChange = (e, key) => {
-    let value = e.target.value
-
-    if (key === 'procMode') {
-      this.setState({
-        procMode: value
-      })
-    }
-    this.props.updateStatus({[key]: value})
-  }
-
-  render() {
-    const { setting, dict } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { funcRules, funcTooltip, procMode } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <div className="model-table-datasource-setting-form-box">
-        <Form {...formItemLayout} className="model-setting-form">
-          <Row gutter={24}>
-            <Col span={12}>
-              <Form.Item label="鎺ュ彛鍚�">
-                {getFieldDecorator('name', {
-                  initialValue: setting.name || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.input'] + '鎺ュ彛鍚�!'
-                    },
-                  ]
-                })(<Input placeholder={''} autoComplete="off" />)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label="鐘舵��">
-                {getFieldDecorator('status', {
-                  initialValue: setting.status || 'true'
-                })(
-                <Radio.Group>
-                  <Radio value="true">鍚敤</Radio>
-                  <Radio value="false">绂佺敤</Radio>
-                </Radio.Group>)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label="鍙傛暟澶勭悊">
-                {getFieldDecorator('procMode', {
-                  initialValue: procMode,
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.select'] + '鍙傛暟澶勭悊鏂瑰紡!'
-                    },
-                  ]
-                })(
-                <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => {this.onRadioChange(e, 'procMode')}}>
-                  <Radio value="script">鍓嶇疆鑴氭湰</Radio>
-                  <Radio value="inner">鍓嶇疆鍑芥暟</Radio>
-                </Radio.Group>)}
-              </Form.Item>
-            </Col>
-            {procMode === 'inner' ? <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title={funcTooltip}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  鍓嶇疆鍑芥暟
-                </Tooltip>
-              }>
-                {getFieldDecorator('prevFunc', {
-                  initialValue: setting.prevFunc || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.input'] + '鍓嶇疆鍑芥暟!'
-                    },
-                    {
-                      max: formRule.func.max,
-                      message: formRule.func.maxMessage
-                    },
-                    ...funcRules
-                  ]
-                })(<Input placeholder={''} autoComplete="off" />)}
-              </Form.Item>
-            </Col> : null}
-            <Col className="data-source" span={24}>
-              <Form.Item label="娴嬭瘯鍦板潃">
-                {getFieldDecorator('interface', {
-                  initialValue: setting.interface || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.input'] + '娴嬭瘯鍦板潃!'
-                    },
-                  ]
-                })(<TextArea rows={2} />)}
-              </Form.Item>
-            </Col>
-            <Col className="data-source" span={24}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title="姝e紡绯荤粺鎵�浣跨敤鐨勭殑鎺ュ彛鍦板潃銆�">
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  姝e紡鍦板潃
-                </Tooltip>
-              }>
-                {getFieldDecorator('proInterface', {
-                  initialValue: setting.proInterface || ''
-                })(<TextArea rows={2} />)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label="璇锋眰鏂瑰紡">
-                {getFieldDecorator('method', {
-                  initialValue: setting.method || 'post',
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.select'] + '璇锋眰鏂瑰紡!'
-                    },
-                  ]
-                })(
-                <Radio.Group>
-                  <Radio value="get">GET</Radio>
-                  <Radio value="post">POST</Radio>
-                </Radio.Group>)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label={
-                <Tooltip placement="topLeft" title={'濡傛灉鑷畾涔夋帴鍙d笉鏀寔璺ㄥ煙璇锋眰锛屼細閫氳繃褰撳墠绯荤粺杞彂銆�'}>
-                  <QuestionCircleOutlined className="mk-form-tip" />
-                  璺ㄥ煙璇锋眰
-                </Tooltip>
-              }>
-                {getFieldDecorator('cross', {
-                  initialValue: setting.cross || 'true'
-                })(
-                <Radio.Group>
-                  <Radio value="true">鏀寔</Radio>
-                  <Radio value="false">涓嶆敮鎸�</Radio>
-                </Radio.Group>)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label="鍥炶皟鏂瑰紡">
-                {getFieldDecorator('callbackType', {
-                  initialValue: setting.callbackType || 'script'
-                })(
-                <Radio.Group onChange={(e) => {this.onRadioChange(e, 'callbackType')}}>
-                  <Radio value="default">榛樿鑴氭湰</Radio>
-                  <Radio value="script">鑷畾涔夎剼鏈�</Radio>
-                </Radio.Group>)}
-              </Form.Item>
-            </Col>
-            <Col span={12}>
-              <Form.Item label="鍥炶皟琛ㄥ悕">
-                {getFieldDecorator('cbTable', {
-                  initialValue: setting.cbTable || '',
-                  rules: [
-                    {
-                      required: true,
-                      message: dict['form.required.input'] + '鍥炶皟琛ㄥ悕!'
-                    },
-                    {
-                      max: 50,
-                      message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!'
-                    }
-                  ]
-                })(<Input placeholder={''} autoComplete="off" />)}
-              </Form.Item>
-            </Col>
-          </Row>
-        </Form>
-      </div>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/baseform/index.scss b/src/menu/sysinterface/settingform/baseform/index.scss
deleted file mode 100644
index aeabe5f..0000000
--- a/src/menu/sysinterface/settingform/baseform/index.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-.model-table-datasource-setting-form-box {
-  position: relative;
-
-  .model-setting-form {
-    .data-source {
-      .ant-form-item-label {
-        width: 16.5%;
-      }
-      .ant-form-item-control-wrapper {
-        width: 83.5%;
-      }
-      .CodeMirror {
-        height: 150px;
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/index.jsx b/src/menu/sysinterface/settingform/index.jsx
deleted file mode 100644
index 6309ec8..0000000
--- a/src/menu/sysinterface/settingform/index.jsx
+++ /dev/null
@@ -1,179 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { fromJS } from 'immutable'
-import { Form, notification, Tabs } from 'antd'
-
-import asyncComponent from '@/utils/asyncComponent'
-import BaseForm from './baseform'
-import zhCN from '@/locales/zh-CN/model.js'
-import enUS from '@/locales/en-US/model.js'
-import './index.scss'
-
-const { TabPane } = Tabs
-const SimpleScript = asyncComponent(() => import('./simplescript'))
-
-class SettingForm extends Component {
-  static propTpyes = {
-    config: PropTypes.object,       // 椤甸潰閰嶇疆淇℃伅
-  }
-
-  state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    formlist: [],
-    btnloading: false,
-    activeKey: 'setting',
-    setting: null,
-    defaultSql: '',
-    status: {}
-  }
-
-  UNSAFE_componentWillMount() {
-    const { config } = this.props
-
-    let _setting = fromJS(config).toJS()
-    let _preScripts = _setting.preScripts || []
-    let _cbScripts = _setting.cbScripts || []
-
-    this.setState({
-      setting: _setting,
-      preScripts: _preScripts,
-      cbScripts: _cbScripts,
-      status: fromJS(_setting).toJS()
-    })
-  }
-
-
-  handleConfirm = () => {
-    const { activeKey, setting, preScripts, cbScripts } = this.state
-
-    let _loading = false
-    if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    }
-
-    if (_loading) {
-      notification.warning({
-        top: 92,
-        message: '瀛樺湪鏈繚瀛樿剼鏈紝璇风偣鍑荤‘瀹氫繚瀛橈紝鎴栫偣鍑诲彇娑堟斁寮冧慨鏀癸紒',
-        duration: 5
-      })
-      return Promise.reject()
-    }
-
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    if (activeKey === 'setting') {
-      return new Promise((resolve, reject) => {
-        this.settingForm.handleConfirm().then(res => {
-          resolve({...res, preScripts, cbScripts})
-        }, () => {
-          reject()
-        })
-      })
-    } else {
-      return new Promise((resolve) => {
-        resolve({...setting, preScripts, cbScripts})
-      })
-    }
-  }
-
-  // 鏍囩鍒囨崲
-  changeTab = (val) => {
-    const { activeKey } = this.state
-
-    let _loading = false
-    if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    }
-
-    if (_loading) {
-      notification.warning({
-        top: 92,
-        message: '瀛樺湪鏈繚瀛樿剼鏈紝璇风偣鍑荤‘瀹氫繚瀛橈紝鎴栫偣鍑诲彇娑堟斁寮冧慨鏀癸紒',
-        duration: 5
-      })
-      return
-    }
-
-    if (activeKey === 'setting') {
-      this.settingForm.handleConfirm().then(res => {
-        this.setState({
-          setting: res,
-          activeKey: val
-        })
-      })
-    } else {
-      this.setState({
-        activeKey: val
-      })
-    }
-  }
-  
-  // 鍓嶇疆鑴氭湰鏇存柊
-  preScriptsUpdate = (preScripts) => {
-    this.setState({preScripts})
-  }
-  
-  // 鍚庣疆鑴氭湰鏇存柊
-  cbScriptsUpdate = (cbScripts) => {
-    this.setState({cbScripts})
-  }
-
-  updateStatus = (status) => {
-    this.setState({status: {...this.state.status, ...status}})
-  }
-
-  render() {
-    const { dict, activeKey, setting, preScripts, cbScripts, status } = this.state
-
-    return (
-      <div className="model-interface-form-box" id="model-interface-form-body">
-        <Tabs activeKey={activeKey} onChange={this.changeTab}>
-          <TabPane tab="鎺ュ彛璁剧疆" key="setting">
-            <BaseForm
-              dict={dict}
-              setting={setting}
-              updateStatus={this.updateStatus}
-              wrappedComponentRef={(inst) => this.settingForm = inst}
-            />
-          </TabPane>
-          <TabPane tab={
-            <span>
-              鍓嶇疆鑴氭湰
-              {preScripts.length ? <span className="count-tip">{preScripts.length}</span> : null}
-            </span>
-          } disabled={status.procMode !== 'script'} key="prescripts">
-            <SimpleScript
-              dict={dict}
-              type="front"
-              setting={setting}
-              scripts={preScripts}
-              scriptsUpdate={this.preScriptsUpdate}
-              wrappedComponentRef={(inst) => this.preScriptsForm = inst}
-            />
-          </TabPane>
-          <TabPane tab={
-            <span>
-              鍥炶皟鑴氭湰
-              {cbScripts.length ? <span className="count-tip">{cbScripts.length}</span> : null}
-            </span>
-          } disabled={status.callbackType !== 'script'} key="cbscripts">
-            <SimpleScript
-              dict={dict}
-              type="back"
-              setting={setting}
-              scripts={cbScripts}
-              scriptsUpdate={this.cbScriptsUpdate}
-              wrappedComponentRef={(inst) => this.cbScriptsForm = inst}
-            />
-          </TabPane>
-        </Tabs>
-      </div>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/index.scss b/src/menu/sysinterface/settingform/index.scss
deleted file mode 100644
index 4d9d692..0000000
--- a/src/menu/sysinterface/settingform/index.scss
+++ /dev/null
@@ -1,61 +0,0 @@
-.model-interface-form-box {
-  position: relative;
-
-  >.ant-spin {
-    position: absolute;
-    top: 150px;
-    left: calc(50% - 16px);
-  }
-  .count-tip {
-    position: absolute;
-    top: 0px;
-    color: #1890ff;
-    font-size: 12px;
-  }
-  .model-table-setting-form {
-    .textarea {
-      .ant-form-item-label {
-        width: 16.3%;
-      }
-      .ant-form-item-control-wrapper {
-        width: 83.33333333%;
-      }
-    }
-    .text-area {
-      .CodeMirror {
-        height: 150px;
-      }
-    }
-  }
-  .operation-btn {
-    display: inline-block;
-    font-size: 16px;
-    padding: 0 5px;
-    cursor: pointer;
-  }
-  td {
-    word-break: break-all;
-  }
-  .setting-custom-back {
-    position: absolute;
-    top: -20px;
-    left: -10px;
-    font-size: 16px;
-    z-index: 1;
-    cursor: pointer;
-    padding: 10px;
-    color: rgb(24, 144, 255);
-  }
-  .to-custom-script {
-    float: right;
-    color: #1890ff;
-    margin-right: 12px;
-    margin-top: 15px;
-    cursor: pointer;
-    border: 0;
-    box-shadow: unset;
-  }
-  .ant-tabs-nav-wrap {
-    text-align: center;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/simplescript/index.jsx b/src/menu/sysinterface/settingform/simplescript/index.jsx
deleted file mode 100644
index 9f13e66..0000000
--- a/src/menu/sysinterface/settingform/simplescript/index.jsx
+++ /dev/null
@@ -1,454 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { fromJS } from 'immutable'
-import { Form, Row, Col, Button, notification, Select, Popconfirm, Typography, Modal, Radio, Tooltip } from 'antd'
-import { StopTwoTone, SwapOutlined, EditOutlined, CheckCircleTwoTone, DeleteOutlined } from '@ant-design/icons'
-import moment from 'moment'
-
-import Utils from '@/utils/utils.js'
-import Api from '@/api'
-import SettingUtils from '../utils'
-import CodeMirror from '@/templates/zshare/codemirror'
-import asyncComponent from '@/utils/asyncComponent'
-import './index.scss'
-
-const { Paragraph } = Typography
-const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
-
-class CustomForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object,         // 瀛楀吀椤�
-    type: PropTypes.string,         // 鑴氭湰绫诲瀷
-    setting: PropTypes.object,      // 璁剧疆
-    scripts: PropTypes.array,       // 鑷畾涔夎剼鏈垪琛�
-    scriptsChange: PropTypes.func,  // 鑷畾涔夎剼鏈垏鎹㈡椂楠岃瘉
-    scriptsUpdate: PropTypes.func   // 琛ㄥ崟
-  }
-
-  state = {
-    editItem: null,
-    loading: false,
-    systemScripts: [],
-    scriptsColumns: [
-      {
-        title: 'SQL',
-        dataIndex: 'sql',
-        width: '60%',
-        render: (text) => {
-          let title = text.match(/^\s*\/\*.+\*\//)
-          title = title && title[0] ? title[0] : ''
-          let _text = title ? text.replace(title, '') : text
-
-          return (
-            <div>
-              {title ? <span style={{color: '#a50'}}>{title}<span style={{fontSize: '12px', marginLeft: '5px'}}>{_text.length}</span></span> : null}
-              <Paragraph copyable={{ text: text }} ellipsis={{ rows: 4, expandable: true }}>{_text}</Paragraph>
-            </div>
-          )
-        }
-      },
-      {
-        title: '鎵ц浣嶇疆',
-        dataIndex: 'position',
-        width: '13%',
-        render: (text, record) => {
-          if (record.position === 'front') {
-            return 'sql鍓�'
-          } else {
-            return 'sql鍚�'
-          }
-        }
-      },
-      {
-        title: '鐘舵��',
-        dataIndex: 'status',
-        width: '12%',
-        render: (text, record) => record.status === 'false' ?
-          (
-            <div>
-              绂佺敤
-              <StopTwoTone style={{marginLeft: '5px'}} twoToneColor="#ff4d4f" />
-            </div>
-          ) :
-          (
-            <div>
-              鍚敤
-              <CheckCircleTwoTone style={{marginLeft: '5px'}} twoToneColor="#52c41a" />
-            </div>
-          )
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '15%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          (<div style={{textAlign: 'center'}}>
-            <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><EditOutlined /></span>
-            <span className="operation-btn" title={this.props.dict['header.form.status.change']} onClick={() => this.handleStatus(record)} style={{color: '#8E44AD'}}><SwapOutlined /></span>
-            <Popconfirm
-              overlayClassName="popover-confirm"
-              title={this.props.dict['model.query.delete']}
-              onConfirm={() => this.handleDelete(record)
-            }>
-              <span className="operation-btn" style={{color: '#ff4d4f'}}><DeleteOutlined /></span>
-            </Popconfirm>
-          </div>)
-      }
-    ]
-  }
-
-  UNSAFE_componentWillMount() {
-    const { scripts } = this.props
-
-    let scriptsColumns = fromJS(this.state.scriptsColumns).toJS()
-
-    this.setState({
-      scripts: fromJS(scripts).toJS(),
-      scriptsColumns
-    })
-  }
-
-  componentDidMount () {
-    this.getsysScript()
-  }
-
-  getsysScript = () => {
-    let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
-
-    _scriptSql = Utils.formatOptions(_scriptSql)
-
-    let _sParam = {
-      func: 'sPC_Get_SelectedList',
-      LText: _scriptSql,
-      obj_name: 'data',
-      arr_field: 'funcname,longparam'
-    }
-    
-    _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
-    _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
-    
-    Api.getSystemConfig(_sParam).then(res => {
-      if (res.status) {
-        let _scripts = res.data.map(item => {
-          let _item = {
-            name: item.funcname,
-            value: window.decodeURIComponent(window.atob(item.longparam))
-          }
-          return _item
-        })
-
-        this.setState({
-          systemScripts: _scripts
-        })
-      } else {
-        notification.warning({
-          top: 92,
-          message: res.message,
-          duration: 5
-        })
-      }
-    })
-  }
-
-  handleCancel = () => {
-    this.setState({
-      editItem: null
-    })
-    this.props.form.setFieldsValue({
-      sql: ''
-    })
-  }
-
-  handleConfirm = () => {
-    const { scripts, editItem } = this.state
-    
-    let _sql = this.props.form.getFieldValue('sql')
-
-    if (!_sql) {
-      notification.warning({
-        top: 92,
-        message: '璇峰~鍐欒嚜瀹氫箟鑴氭湰锛�',
-        duration: 5
-      })
-      return
-    } else if (/^\s+$/.test(_sql)) {
-      notification.warning({
-        top: 92,
-        message: '鑷畾涔夎剼鏈笉鍙负绌猴紒',
-        duration: 5
-      })
-      return
-    }
-
-    let values = {
-      uuid: editItem && editItem.uuid ? editItem.uuid : Utils.getuuid(),
-      sql: _sql,
-    }
-
-    if (this.props.form.getFieldValue('position')) {
-      values.position = this.props.form.getFieldValue('position')
-    }
-
-    let _quot = values.sql.match(/'{1}/g)
-    let _lparen = values.sql.match(/\({1}/g)
-    let _rparen = values.sql.match(/\){1}/g)
-
-    _quot = _quot ? _quot.length : 0
-    _lparen = _lparen ? _lparen.length : 0
-    _rparen = _rparen ? _rparen.length : 0
-
-    if (_quot % 2 !== 0) {
-      notification.warning({
-        top: 92,
-        message: 'sql涓璡'蹇呴』鎴愬鍑虹幇',
-        duration: 5
-      })
-      return
-    } else if (_lparen !== _rparen) {
-      notification.warning({
-        top: 92,
-        message: 'sql涓�()蹇呴』鎴愬鍑虹幇',
-        duration: 5
-      })
-      return
-    } else if (/--/ig.test(values.sql)) {
-      notification.warning({
-        top: 92,
-        message: '鑷畾涔塻ql璇彞涓紝涓嶅彲鍑虹幇瀛楃 -- 锛屾敞閲婅鐢� /*鍐呭*/',
-        duration: 5
-      })
-      return
-    }
-
-    let error = Utils.verifySql(values.sql, 'customscript')
-
-    if (error) {
-      notification.warning({
-        top: 92,
-        message: 'sql涓笉鍙娇鐢�' + error,
-        duration: 5
-      })
-      return
-    }
-
-    let _scripts = fromJS(scripts).toJS()
-
-    if (editItem && editItem.uuid) {
-      _scripts = _scripts.map(item => {
-        if (item.uuid === values.uuid) {
-          return values
-        } else {
-          return item
-        }
-      })
-    } else {
-      _scripts.push(values)
-    }
-
-    let param = {
-      func: 's_debug_sql',
-      exec_type: 'y',
-      LText: SettingUtils.getCustomDebugSql(_scripts)
-    }
-
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.LText = param.LText.replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'${param.timestamp}'`)
-    param.LText = Utils.formatOptions(param.LText)
-    param.secretkey = Utils.encrypt('', param.timestamp)
-    
-    this.setState({loading: true})
-    Api.genericInterface(param).then(result => {
-      if (result.status) {
-        this.setState({
-          loading: false,
-          scripts: _scripts,
-          editItem: null
-        })
-  
-        this.props.scriptsUpdate(_scripts)
-        this.props.form.setFieldsValue({
-          sql: ''
-        })
-      } else {
-        this.setState({loading: false})
-        Modal.error({
-          title: result.message
-        })
-      }
-    })
-  }
-
-  selectScript = (value, option) => {
-    if (!value || !option) return
-    let _sql = this.props.form.getFieldValue('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
-    })
-  }
-
-  handleEdit = (record) => {
-    const { type } = this.props
-    this.setState({
-      editItem: record
-    })
-
-    if (type === 'front') {
-      this.props.form.setFieldsValue({
-        sql: record.sql
-      })
-    } else {
-      this.props.form.setFieldsValue({
-        sql: record.sql,
-        position: record.position || 'back'
-      })
-    }
-
-    this.scrolltop()
-  }
-
-  scrolltop = () => {
-    let node = document.getElementById('model-interface-form-body').parentNode
-
-    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)
-    }
-  }
-
-  changeScripts = (scripts) => {
-    this.setState({scripts})
-    this.props.scriptsUpdate(scripts)
-  }
-
-  handleStatus = (record) => {
-    let scripts = fromJS(this.state.scripts).toJS()
-    record.status = record.status === 'false' ? 'true' : 'false'
-
-    scripts = scripts.map(item => {
-      if (item.uuid === record.uuid) {
-        return record
-      } else {
-        return item
-      }
-    })
-
-    this.setState({scripts})
-    this.props.scriptsUpdate(scripts)
-  }
-
-  handleDelete = (record) => {
-    let scripts = fromJS(this.state.scripts).toJS()
-    scripts = scripts.filter(item => item.uuid !== record.uuid)
-
-    this.setState({ scripts })
-    this.props.scriptsUpdate(scripts)
-  }
-
-  render() {
-    const { setting, scripts, type } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { scriptsColumns, systemScripts } = this.state
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    return (
-      <div className="modal-menu-setting-script">
-        <Form {...formItemLayout}>
-          <Row gutter={24}>
-            <Col span={8}>
-              <Form.Item label={'鍥炶皟琛ㄥ悕'} style={{whiteSpace: 'nowrap', margin: 0}}>
-                {setting.cbTable}
-              </Form.Item>
-            </Col>
-            <Col span={16}>
-              <Form.Item label={'鎶ラ敊瀛楁'} style={{margin: 0}}>
-                ErrorCode, retmsg
-              </Form.Item>
-            </Col>
-            <Col span={24} className="sqlfield">
-              <Form.Item label={'鍙敤瀛楁'}>
-                <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id</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>
-              </Form.Item>
-            </Col>
-            {type === 'back' ? <Col span={8} style={{whiteSpace: 'nowrap'}}>
-              <Form.Item style={{marginBottom: 0}} label="鎵ц浣嶇疆">
-                {getFieldDecorator('position', {
-                  initialValue: 'front'
-                })(
-                  <Radio.Group>
-                    <Radio value="front">sql鍓�</Radio>
-                    <Radio value="back">sql鍚�</Radio>
-                  </Radio.Group>
-                )}
-              </Form.Item>
-            </Col> : null}
-            <Col span={10} className="quick-add">
-              <Form.Item label={'蹇嵎娣诲姞'} style={{marginBottom: 0}}>
-                <Select
-                  allowClear
-                  showSearch
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={this.selectScript}
-                >
-                  {type === 'back' ? <Select.Option key="default" value={`declare @${setting.cbTable} table (mk_api_key nvarchar(100),mk_level nvarchar(10),mk_id nvarchar(50),mk_bid nvarchar(50))\n/*@${setting.cbTable}_data table (mk_level nvarchar(10),mk_id nvarchar(50),mk_bid nvarchar(50))*/`}>榛樿sql</Select.Option> : null}
-                  {systemScripts.map((option, i) =>
-                    <Select.Option style={{whiteSpace: 'normal'}} key={i} value={option.value}>{option.name}</Select.Option>
-                  )}
-                </Select>
-              </Form.Item>
-            </Col>
-            <Col span={6} className="add">
-              <Button onClick={this.handleConfirm} loading={this.state.loading} className="mk-green" style={{marginTop: 5, marginBottom: 15, marginLeft: 30}}>
-                淇濆瓨
-              </Button>
-              <Button onClick={this.handleCancel} style={{marginTop: 5, marginBottom: 15, marginLeft: 10}}>
-                鍙栨秷
-              </Button>
-            </Col>
-            <Col span={24} className="sql">
-              <Form.Item label={'sql'}>
-                {getFieldDecorator('sql', {
-                  initialValue: ''
-                })(<CodeMirror />)}
-              </Form.Item>
-            </Col>
-          </Row>
-        </Form>
-        <EditTable data={scripts} actions={['move']} columns={scriptsColumns} onChange={this.changeScripts}/>
-      </div>
-    )
-  }
-}
-
-export default Form.create()(CustomForm)
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/simplescript/index.scss b/src/menu/sysinterface/settingform/simplescript/index.scss
deleted file mode 100644
index 945809b..0000000
--- a/src/menu/sysinterface/settingform/simplescript/index.scss
+++ /dev/null
@@ -1,45 +0,0 @@
-.modal-menu-setting-script {
-  .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%;
-    }
-  }
-  .quick-add {
-    .ant-col-sm-8 {
-      width: 26%;
-    }
-    .ant-col-sm-16 {
-      width: 74%;
-    }
-  }
-  .sql {
-    .ant-col-sm-8 {
-      width: 10.5%;
-    }
-    .ant-col-sm-16 {
-      width: 89.5%;
-      padding-top: 4px;
-    }
-    .CodeMirror {
-      height: 350px;
-    }
-  }
-  div.ant-typography {
-    margin-bottom: 0;
-  }
-}
\ No newline at end of file
diff --git a/src/menu/sysinterface/settingform/utils.jsx b/src/menu/sysinterface/settingform/utils.jsx
deleted file mode 100644
index c532c3f..0000000
--- a/src/menu/sysinterface/settingform/utils.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-
-export default class SettingUtils {
-  /**
-   * @description 鐢熸垚鍓嶇疆鎴栧悗缃鍙�
-   * @return {String}  scripts       鑴氭湰
-   */
-  static getCustomDebugSql (scripts) {
-    let sql = ''
-    let _customScript = ''
-
-    scripts.forEach(script => {
-      if (script.status === 'false') return
-
-      _customScript += `
-      ${script.sql}
-      `
-    })
-
-    if (_customScript) {
-      _customScript = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100) select @ErrorCode='',@retmsg =''
-        ${_customScript}
-      `
-    }
-
-    _customScript = _customScript.replace(/@\$|\$@/ig, '')
-    _customScript = _customScript.replace(/@userName@|@fullName@/ig, `''`)
-    // 澶栬仈鏁版嵁搴撴浛鎹�
-    if (window.GLOB.externalDatabase !== null) {
-      _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
-    }
-
-    if (_customScript) {
-      sql = `/* sql 楠岃瘉 */
-        ${_customScript}
-        aaa:
-        if @ErrorCode!=''
-          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
-      `
-    }
-    sql = sql.replace(/\n\s{8}/ig, '\n')
-    console.info(sql)
-
-    return sql
-  }
-}
\ No newline at end of file
diff --git a/src/menu/tablenodes/index.jsx b/src/menu/tablenodes/index.jsx
new file mode 100644
index 0000000..8f31c88
--- /dev/null
+++ b/src/menu/tablenodes/index.jsx
@@ -0,0 +1,426 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Button, notification, Spin, Input } from 'antd'
+import { ForkOutlined } from '@ant-design/icons'
+
+import Api from '@/api'
+import G6 from "@antv/g6"
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+const { Search } = Input
+
+class TableNodes extends Component {
+  static propTpyes = {
+    config: PropTypes.object
+  }
+
+  state = {
+    visible: false,
+    loading: false,
+    nodes: null,
+    empty: false
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  getTbs = (config) => {
+    let tbs = []
+    let ptbs = []
+
+    let traversal = (components) => {
+      components.forEach(item => {
+        if (item.$tables) {
+          ptbs.push(...item.$tables)
+          item.$tables.forEach(tb => {
+            tbs.push({
+              label: item.name,
+              table: tb,
+              color: '#5AD8A6',
+              id: Utils.getuuid(),
+              direction: 'left'
+            })
+          })
+        }
+        if (item.type === 'tabs') {
+          item.subtabs.forEach(tab => {
+            traversal(tab.components)
+          })
+        } else if (item.type === 'group') {
+          traversal(item.components)
+        }
+      })
+    }
+
+    traversal(config.components)
+
+    return {tbs, ptbs}
+  }
+
+  trigger = () => {
+    const { config } = this.props
+
+    if (!config) return
+
+    this.setState({visible: true, loading: true, empty: false}, () => {
+      let param = {
+        func: 's_get_menus_tb_list',
+        TypeCharOne: sessionStorage.getItem('kei_no') || '',
+        typename: sessionStorage.getItem('typename') || '',
+        MenuID: config.uuid
+      }
+
+      Api.getSystemConfig(param).then(result => {
+        if (!result.status) {
+          notification.warning({
+            top: 92,
+            message: result.message,
+            duration: 5
+          })
+
+          this.setState({empty: true, loading: false})
+
+          return
+        }
+
+        let data = {
+          label: config.MenuName || '绌�',
+          id: config.uuid,
+          MenuID: config.MenuID,
+          children: []
+        }
+
+        let { tbs, ptbs } = this.getTbs(config)
+
+        ptbs = Array.from(new Set(ptbs))
+        ptbs.sort()
+        if (ptbs.length && sessionStorage.getItem('mk_tb_names')) {
+          let names = sessionStorage.getItem('mk_tb_names')
+          ptbs = ptbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+        }
+
+        if (ptbs.length) {
+          ptbs.forEach((item, i) => {
+            let cell = {
+              label: item,
+              id: 'par' + i,
+              direction: 'left',
+              color: '#5AD8A6',
+              children: []
+            }
+
+            tbs.forEach(t => {
+              if (t.table === item) {
+                cell.children.push(t)
+              }
+            })
+
+            data.children.push(cell)
+          })
+        }
+
+        if (result.tb_list) {
+          result.tb_list.sort((a, b) => a.tbname > b.tbname ? 1 : -1)
+          result.tb_list.forEach((item, i) => {
+            let cell = {
+              label: item.tbname,
+              name: item.tbname.toLowerCase(),
+              id: 'table' + i,
+              direction: 'right',
+              color: '#1890ff',
+              children: []
+            }
+
+            if (item[item.tbname]) {
+              item[item.tbname].forEach((m, i) => {
+                if (m.debug_url) {
+                  let _param = JSON.parse(window.decodeURIComponent(window.atob(m.debug_url)))
+                  let label = _param.MenuName
+
+                  if (_param && _param.type === 'app') {
+                    label += ` (${_param.kei_no} | ${_param.typename}${param.lang !== 'zh-CN' ? ' | ' + param.lang : ''})`
+                  }
+
+                  cell.children.push({
+                    label: label,
+                    id: item.tbname + 'menu' + i,
+                    direction: 'right',
+                    color: '#1890ff',
+                    param: _param
+                  })
+                }
+              })
+            }
+
+            data.children.push(cell)
+          })
+        }
+        
+        if (data.children.length === 0) {
+          this.setState({empty: true, loading: false})
+        } else {
+          this.setState({loading: false, nodes: data})
+          this.getForks(data)
+        }
+      })
+    })
+  }
+
+  changeMenu = (menu) => {
+    if (menu.direction !== 'right') return
+
+    if (menu.depth === 1) {
+      window.open('#/hs')
+    } else if (menu.param) {
+      if (menu.param.type === 'admin') {
+        if (menu.param.MenuType === 'custom') {
+          let _param = {...menu.param}
+          delete _param.type
+          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
+          window.open(`#/menudesign/${_param}`)
+        }
+      } else if (menu.param.type === 'app') {
+        if (menu.param.typename !== 'pc') {
+          let _param = {...menu.param}
+          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
+          window.open(`#/mobdesign/${_param}`)
+        } else {
+          let _param = {...menu.param}
+          _param = window.btoa(window.encodeURIComponent(JSON.stringify(_param)))
+          window.open(`#/pcdesign/${_param}`)
+        }
+      }
+    }
+  }
+
+  resetNodes = (key) => {
+    let data = fromJS(this.state.nodes).toJS()
+    key = key ? key.toLowerCase() : ''
+
+    data.children.forEach(cell => {
+      if (cell.direction === 'right') {
+        cell.fontcolor = ''
+        if (key && cell.name.indexOf(key) > -1) {
+          cell.fontcolor = 'orange'
+        }
+      }
+    })
+    let _element = document.getElementById('mkTableNode')
+    if (_element) {
+      _element.innerHTML = ''
+    }
+
+    this.setState({}, () => {
+      this.getForks(data)
+    })
+  }
+
+  getForks = (data) => {
+    const { Util } = G6
+    const that = this
+    
+    G6.registerNode(
+      'dice-mind-map-root', {
+        jsx: (cfg) => {
+          const width = Util.getTextSize(cfg.label, 14)[0] + 12;
+          const stroke = cfg.style.stroke || '#096dd9';
+    
+          return `
+          <group>
+            <rect draggable="true" style={{width: ${width}, height: 30, stroke: ${stroke}, radius: 4}} keyshape>
+              <text style={{ fontSize: 14, marginLeft: 6, marginTop: 6 }}>${cfg.label}</text>
+            </rect>
+          </group>
+        `;
+        },
+        getAnchorPoints() {
+          return [
+            [0, 0.5],
+            [1, 0.5],
+          ];
+        },
+      },
+      'single-node',
+    );
+
+    G6.registerNode(
+      'dice-mind-map-leaf', {
+        jsx: (cfg) => {
+          const width = Util.getTextSize(cfg.label, 12)[0] + 24;
+          const color = cfg.color;
+    
+          return `
+          <group>
+            <rect draggable="true" style={{width: ${width}, height: 26, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, fill: 'transparent' }}>
+              <text style={{ fontSize: 12, fill: ${cfg.fontcolor ? cfg.fontcolor : 'black'}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, marginLeft: 12, marginTop: 6 }}>${cfg.label}</text>
+            </rect>
+            <rect style={{ fill: ${color}, width: ${width}, cursor: ${cfg.direction !== 'left' ? 'pointer' : 'default'}, height: 2, x: 0, y: 32 }} />
+          </group>
+        `;
+        },
+        getAnchorPoints() {
+          return [
+            [0, 0.965],
+            [1, 0.965],
+          ];
+        },
+      },
+      'single-node',
+    );
+    G6.registerBehavior('dice-mindmap', {
+      getEvents() {
+        return {
+          'node:dblclick': 'editNode',
+        };
+      },
+      editNode(evt) {
+        const item = evt.item;
+        const model = item.get('model');
+        
+        that.changeMenu(model)
+      }
+    });
+    G6.registerBehavior('scroll-canvas', {
+      getEvents: function getEvents() {
+        return {
+          wheel: 'onWheel',
+        };
+      },
+    
+      onWheel: function onWheel(ev) {
+        const {
+          graph
+        } = this;
+        if (!graph) {
+          return;
+        }
+        if (ev.ctrlKey) {
+          const canvas = graph.get('canvas');
+          const point = canvas.getPointByClient(ev.clientX, ev.clientY);
+          let ratio = graph.getZoom();
+          if (ev.wheelDelta > 0) {
+            ratio += ratio * 0.05;
+          } else {
+            ratio *= ratio * 0.05;
+          }
+          graph.zoomTo(ratio, {
+            x: point.x,
+            y: point.y,
+          });
+        } else {
+          const x = ev.deltaX || ev.movementX;
+          const y = ev.deltaY || ev.movementY || (-ev.wheelDelta * 125) / 3;
+          graph.translate(-x, -y);
+        }
+        ev.preventDefault();
+      },
+    });
+    
+    const dataTransform = (data) => {
+      const changeData = (d, level = 0, color) => {
+        const data = {
+          ...d,
+        };
+        switch (level) {
+          case 0:
+            data.type = 'dice-mind-map-root';
+            break;
+          default:
+            data.type = 'dice-mind-map-leaf';
+            break;
+        }
+    
+        data.hover = false;
+    
+        if (color) {
+          data.color = color;
+        }
+    
+        if (d.children) {
+          data.children = d.children.map((child) => changeData(child, level + 1, data.color));
+        }
+        return data;
+      };
+      return changeData(data);
+    };
+
+    const tree = new G6.TreeGraph({
+      container: 'mkTableNode',
+      width: this.wrap.offsetWidth,
+      height: this.wrap.offsetHeight,
+      fitView: true,
+      fitViewPadding: [10, 20],
+      layout: {
+        type: 'mindmap',
+        direction: 'H',
+        getHeight: () => {
+          return 16;
+        },
+        getWidth: (node) => {
+          return node.level === 0 ?
+            Util.getTextSize(node.label, 16)[0] + 12 :
+            Util.getTextSize(node.label, 12)[0];
+        },
+        getVGap: () => {
+          return 10;
+        },
+        getHGap: () => {
+          return 60;
+        },
+        getSide: (node) => {
+          return node.data.direction;
+        },
+      },
+      defaultEdge: {
+        type: 'cubic-horizontal',
+        style: {
+          lineWidth: 2,
+        },
+      },
+      minZoom: 0.5,
+      modes: {
+        default: ['drag-canvas', 'zoom-canvas', 'dice-mindmap'],
+      },
+    });
+    
+    tree.data(dataTransform(data));
+    
+    tree.render();
+  }
+
+  render() {
+    const { visible, loading, empty } = this.state
+
+    return (
+      <div style={{display: 'inline-block'}}>
+        <Button style={{borderColor: '#8E44AD', color: '#8E44AD'}} onClick={this.trigger}><ForkOutlined /> 琛ㄥ叧绯诲浘</Button>
+        <Modal
+          title=""
+          wrapClassName="view-table-modal"
+          visible={visible}
+          width={'90vw'}
+          closable={false}
+          maskClosable={false}
+          footer={[]}
+          destroyOnClose
+        >
+          <div className="header">琛ㄥ叧绯诲浘</div>
+          <Search className="tb-search" placeholder="璇疯緭鍏ヨ〃鍚�" onSearch={value => this.resetNodes(value)} enterButton />
+          <div className="wrap">
+            {loading ? <Spin size="large" /> : null}
+            {empty ? <div className="empty">鏈煡璇㈠埌琛ㄥ悕淇℃伅銆�</div> : null}
+            <div className="mountNode" id="mkTableNode" ref={ref => this.wrap = ref}></div>
+          </div>
+          <div className="footer">
+            <Button key="cancel" onClick={() => { this.setState({ visible: false })}}>鍏抽棴</Button>
+          </div>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default TableNodes
\ No newline at end of file
diff --git a/src/menu/tablenodes/index.scss b/src/menu/tablenodes/index.scss
new file mode 100644
index 0000000..669585c
--- /dev/null
+++ b/src/menu/tablenodes/index.scss
@@ -0,0 +1,54 @@
+.view-table-modal {
+  .ant-modal {
+    top: 55px;
+  }
+  .ant-modal-body {
+    padding: 20px 50px 20px;
+    user-select: none;
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+  .wrap {
+    position: relative;
+    height: calc(100vh - 200px);
+    margin: 10px 0px;
+    overflow: hidden;
+
+    .mountNode {
+      height: 100%;
+    }
+
+    .ant-spin {
+      position: absolute;
+      top: calc(50% - 16px);
+      left: calc(50% - 16px);
+    }
+    .empty {
+      position: relative;
+      text-align: center;
+      color: #959595;
+      padding-top: 200px;
+    }
+    .empty + .mountNode {
+      opacity: 0;
+    }
+  }
+  .header {
+    color: #1890ff;
+    font-weight: 500;
+    text-align: center;
+    font-size: 18px;
+  }
+
+  .footer {
+    text-align: center;
+  }
+  .tb-search {
+    position: absolute;
+    width: 200px;
+    z-index: 1;
+    right: 40px;
+    top: 16px;
+  }
+}
\ No newline at end of file
diff --git a/src/pc/bgcontroller/index.jsx b/src/pc/bgcontroller/index.jsx
index 23ee485..35def8d 100644
--- a/src/pc/bgcontroller/index.jsx
+++ b/src/pc/bgcontroller/index.jsx
@@ -215,28 +215,28 @@
             className="normal-view"
             label={<ArrowUpOutlined title="涓婅竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
+            <StyleInput defaultValue={config.style.paddingTop || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingTop')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
+            <StyleInput defaultValue={config.style.paddingBottom || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingBottom')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
+            <StyleInput defaultValue={config.style.paddingLeft || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingLeft')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/>
+            <StyleInput defaultValue={config.style.paddingRight || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'paddingRight')}/>
           </Form.Item>
           <p className="normal-view" style={{borderBottom: '1px solid #eaeaea', color: '#40a9ff'}}>澶栬竟璺�</p>
           <Form.Item
@@ -244,28 +244,28 @@
             className="normal-view"
             label={<ArrowUpOutlined title="涓婅竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.marginTop || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginTop')}/>
+            <StyleInput defaultValue={config.style.marginTop || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginTop')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowDownOutlined title="涓嬭竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.marginBottom || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginBottom')}/>
+            <StyleInput defaultValue={config.style.marginBottom || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginBottom')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowLeftOutlined title="宸﹁竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.marginLeft || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginLeft')}/>
+            <StyleInput defaultValue={config.style.marginLeft || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginLeft')}/>
           </Form.Item>
           <Form.Item
             colon={false}
             className="normal-view"
             label={<ArrowRightOutlined title="鍙宠竟璺�"/>}
           >
-            <StyleInput defaultValue={config.style.marginRight || '0px'} options={['px', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginRight')}/>
+            <StyleInput defaultValue={config.style.marginRight || '0px'} options={['px', '%', 'vh', 'vw']} onChange={(val) => this.changePadding(val, 'marginRight')}/>
           </Form.Item>
         </Form>
       </div>
diff --git a/src/store/action-type.js b/src/store/action-type.js
index c65f4df..9443fa6 100644
--- a/src/store/action-type.js
+++ b/src/store/action-type.js
@@ -13,11 +13,5 @@
 // 閲嶇疆缂栬緫绾у埆
 export const RESET_EDITLEVEL = 'RESET_EDITLEVEL'
 
-// 鍒濆鍖栨寜閽潈闄�
-export const INIT_ACTIONPERMISSION = 'INIT_ACTIONPERMISSION'
-
-// 鍒濆鍖栬彍鍗曟潈闄�
-export const INIT_MENUPERMISSION = 'INIT_MENUPERMISSION'
-
 // 閫�鍑�
 export const LOGOUT = 'LOGOUT'
\ No newline at end of file
diff --git a/src/store/action.js b/src/store/action.js
index b4bbf15..c0115e7 100644
--- a/src/store/action.js
+++ b/src/store/action.js
@@ -32,22 +32,6 @@
   }
 }
 
-// 鍒濆鍖栨寜閽潈闄�
-export const initActionPermission = (permAction) => {
-  return {
-    type: user.INIT_ACTIONPERMISSION,
-    permAction: permAction
-  }
-}
-
-// 鍒濆鍖栬彍鍗曟潈闄�
-export const initMenuPermission = (permMenus) => {
-  return {
-    type: user.INIT_MENUPERMISSION,
-    permMenus: permMenus
-  }
-}
-
 // 閫�鍑洪噸缃�
 export const logout = () => {
   return {
diff --git a/src/store/reducer.js b/src/store/reducer.js
index 4729c77..b33716d 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.js
@@ -8,8 +8,6 @@
   mainMenu: _mainMenu,  // 宸查�変富鑿滃崟
   collapse: _collapse,  // 鏄惁鏀惰捣渚ц竟鏍忓鑸�
   editLevel: null,      // 缂栬緫鑿滃崟绾у埆锛屽�间负level1銆乴evel2銆乴evel3銆丠S
-  permAction: {},       // 鐢ㄦ埛鎸夐挳鏉冮檺
-  permMenus: [],        // 鐢ㄦ埛涓夌骇鑿滃崟鍒楄〃
 }
 
 // 鐢ㄦ埛娑堟伅
@@ -39,26 +37,12 @@
         ...state,
         editLevel: action.editLevel
       }
-    case Type.INIT_ACTIONPERMISSION:
-    // 鍒濆鍖栨寜閽潈闄�
-      return {
-        ...state,
-        permAction: action.permAction
-      }
-    case Type.INIT_MENUPERMISSION:
-    // 鍒濆鍖栦笁绾ц彍鍗曟潈闄�
-      return {
-        ...state,
-        permMenus: action.permMenus
-      }
     case Type.LOGOUT:
       return {
         menuTree: null,
         mainMenu: null,
         collapse: localStorage.getItem('collapse') === 'true',
-        editLevel: null,
-        permAction: {},
-        permMenus: [],
+        editLevel: null
       }
     default:
       return state
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index 14f6e16..a20277d 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Tabs, Switch, Row, Col } from 'antd'
 
@@ -76,7 +75,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, permMenus, param, MenuName, MenuID } = this.props
+    const { param, MenuName, MenuID } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -159,13 +158,13 @@
 
       // 鏉冮檺杩囨护
       if (!window.GLOB.mkHS) {
-        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
+        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
         config.tabgroups.forEach(group => {
           group.sublist = group.sublist.filter(tab => {
             if (tab.supMenu === 'mainTable') {
               tab.supMenu = MenuID
             }
-            return permAction[tab.linkTab]
+            return window.GLOB.mkActions[tab.linkTab]
           })
         })
       } else {
@@ -336,7 +335,7 @@
 
           if (col.linkmenu && col.linkmenu.length > 0) {
             let menu_id = col.linkmenu.slice(-1)[0]
-            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
           } else {
             col.linkThdMenu = ''
           }
@@ -1266,22 +1265,11 @@
         }
         {!window.GLOB.mkHS && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config} /> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
+        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction,
-    permMenus: state.permMenus
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
\ No newline at end of file
+export default NormalTable
\ No newline at end of file
diff --git a/src/tabviews/calendar/index.jsx b/src/tabviews/calendar/index.jsx
index c7485e1..cd7b465 100644
--- a/src/tabviews/calendar/index.jsx
+++ b/src/tabviews/calendar/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Modal, Button } from 'antd'
 import moment from 'moment'
@@ -22,7 +21,7 @@
 const SubTabTable = asyncSpinComponent(() => import('@/tabviews/subtabtable'))
 const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
 
-class NormalTable extends Component {
+class MkCalendar extends Component {
   static propTpyes = {
     param: PropTypes.any,        // 鍏朵粬椤甸潰浼犻�掔殑鍙傛暟
     MenuID: PropTypes.string,    // 鑿滃崟Id
@@ -55,7 +54,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, param } = this.props
+    const { param } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -107,7 +106,7 @@
 
       // 鏉冮檺杩囨护
       if (!window.GLOB.mkHS) {
-        if (config.tab && !permAction[config.tab.linkTab]) {
+        if (config.tab && !window.GLOB.mkActions[config.tab.linkTab]) {
           config.tab = null
         }
       }
@@ -574,14 +573,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
\ No newline at end of file
+export default MkCalendar
\ No newline at end of file
diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index b861521..940775d 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Tabs, Switch, Row, Col } from 'antd'
 
@@ -28,6 +27,7 @@
 const ChartComponent = asyncSpinComponent(() => import('@/tabviews/zshare/chartcomponent'))
 const PagemsgComponent = asyncComponent(() => import('@/tabviews/zshare/pageMessage'))
 const AutoMatic = asyncComponent(() => import('@/tabviews/zshare/automatic'))
+const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
 
 const { TabPane } = Tabs
 
@@ -69,14 +69,15 @@
     absFields: [],        // 缁濆鍊煎瓧娈�
     loadCustomApi: true,  // 鍔犺浇澶栭儴璧勬簮
     hasReqFields: false,
-    autoMatic: null
+    autoMatic: null,
+    visible: false
   }
 
   /**
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, permMenus, param, MenuName, MenuID } = this.props
+    const { param, MenuName, MenuID } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -159,13 +160,13 @@
 
       // 鏉冮檺杩囨护
       if (!window.GLOB.mkHS) {
-        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
+        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
         config.tabgroups.forEach(group => {
           group.sublist = group.sublist.filter(tab => {
             if (tab.supMenu === 'mainTable') {
               tab.supMenu = MenuID
             }
-            return permAction[tab.linkTab]
+            return window.GLOB.mkActions[tab.linkTab]
           })
         })
       } else {
@@ -336,7 +337,7 @@
 
           if (col.linkmenu && col.linkmenu.length > 0) {
             let menu_id = col.linkmenu.slice(-1)[0]
-            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
           } else {
             col.linkThdMenu = ''
           }
@@ -432,7 +433,7 @@
         chartId,
         config,
         statFields,
-        shortcuts,
+        shortcuts: shortcuts.length > 0 ? shortcuts : null,
         setting: config.setting,
         searchlist: config.search,
         actions: _actions,
@@ -463,11 +464,6 @@
   setShortcut = () => {
     const { shortcuts } = this.state
 
-    if (!shortcuts || shortcuts.length === 0) {
-      document.onkeydown = () => {}
-      return
-    }
-
     document.onkeydown = (event) => {
       let e = event || window.event
       let keyCode = e.keyCode || e.which || e.charCode
@@ -484,6 +480,16 @@
       if (!preKey || !keyCode) return
 
       let _shortcut = `${preKey}+${keyCode}`
+
+      if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
+        window.debugger = false
+        window.GLOB.breakpoint = false
+        sessionStorage.removeItem('breakpoint')
+        
+        MKEmitter.emit('debugChange')
+      }
+
+      if (!shortcuts) return
 
       shortcuts.some(item => {
         if (item.$shortcut === _shortcut) {
@@ -1090,6 +1096,10 @@
     }
   }
 
+  debugChange = () => {
+    this.setState({visible: !this.state.visible})
+  }
+
   UNSAFE_componentWillMount () {
     // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
     this.loadconfig()
@@ -1101,6 +1111,7 @@
 
   componentDidMount () {
     MKEmitter.addListener('reloadData', this.reloadData)
+    MKEmitter.addListener('debugChange', this.debugChange)
     MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.addListener('changeTableLine', this.changeTableLine)
     MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
@@ -1117,6 +1128,7 @@
     }
     document.onkeydown = () => {}
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('debugChange', this.debugChange)
     MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.removeListener('changeTableLine', this.changeTableLine)
     MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
@@ -1273,24 +1285,14 @@
             })}
           </Tabs>))
         }
+        {setting && window.GLOB.breakpoint ? <DebugTable /> : null}
         {!window.GLOB.mkHS && autoMatic ? <AutoMatic autoMatic={autoMatic} config={config} /> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
+        {!window.GLOB.mkHS && setting ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction,
-    permMenus: state.permMenus
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
\ No newline at end of file
+export default NormalTable
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx
index c00e0fa..e9aa506 100644
--- a/src/tabviews/custom/components/card/balcony/index.jsx
+++ b/src/tabviews/custom/components/card/balcony/index.jsx
@@ -50,13 +50,13 @@
       BID = BData.$BID || ''
     }
     
-    if (_config.wrap.datatype !== 'static') {
+    if (_config.wrap.datatype === 'dynamic') {
       _sync = _config.setting.sync === 'true'
 
       if (_sync && data) {
-        _data = data[_config.dataName] || {}
+        _data = data[_config.dataName] || {$$empty: true}
         if (_data && Array.isArray(_data)) {
-          _data = _data[0] || {}
+          _data = _data[0] || {$$empty: true}
         }
         _sync = false
       } else if (_sync && initdata) {
@@ -66,10 +66,15 @@
         }
         _sync = false
       }
+    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
+      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
+      _data = fromJS(_data).toJS()
     }
 
-    if (_data) {
-      _data.$$BID = BID || ''
+    _data.$$BID = BID || ''
+    _data.$$BData = BData || ''
+    if (_config.setting.primaryKey) {
+      _data.$$uuid = _data[_config.setting.primaryKey] || ''
     }
 
     if (_config.wrap.position === 'fixed' || _config.wrap.position === 'absolute') {
@@ -113,7 +118,7 @@
       config: _config,
       arr_field: _config.columns.map(col => col.field).join(','),
     }, () => {
-      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true') {
+      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true') {
         setTimeout(() => {
           this.loadData()
         }, _config.setting.delay || 0)
@@ -129,8 +134,12 @@
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
+
+    if (config.wrap.datatype === 'public') {
+      MKEmitter.addListener('mkPublicData', this.mkPublicData)
+    }
     
-    if (config.timer) {
+    if (config.timer && config.wrap.datatype === 'dynamic') {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
     }
@@ -145,6 +154,7 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('mkPublicData', this.mkPublicData)
     MKEmitter.removeListener('syncBalconyData', this.syncBalconyData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
@@ -157,25 +167,39 @@
    * @description 鍥捐〃鏁版嵁鏇存柊锛屽埛鏂板唴瀹�
    */
   UNSAFE_componentWillReceiveProps (nextProps) {
-    const { sync, config, BID } = this.state
+    const { sync, config, BID, BData } = this.state
 
     if (sync && !is(fromJS(this.props.data), fromJS(nextProps.data))) {
       let _data = {$$empty: true}
       if (nextProps.data && nextProps.data[config.dataName]) {
         _data = nextProps.data[config.dataName]
         if (_data && Array.isArray(_data)) {
-          _data = _data[0]
+          _data = _data[0] || {$$empty: true}
         }
       }
 
-      if (_data) {
-        _data.$$BID = BID || ''
-      }
+      _data.$$BID = BID || ''
+      _data.$$BData = BData || ''
+      _data.$$uuid = _data[config.setting.primaryKey] || ''
 
       this.setState({sync: false, data: _data})
     }
   }
 
+  mkPublicData = (publicId, data) => {
+    const { config, BID, BData } = this.state
+
+    if (config.wrap.datatype === 'public' && config.wrap.publicId === publicId) {
+      let _data = fromJS(data).toJS()
+
+      _data.$$BID = BID || ''
+      _data.$$BData = BData || ''
+      _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+      this.setState({data: _data})
+    }
+  }
+
   /**
    * @description 鎸夐挳鎵ц瀹屾垚鍚庨〉闈㈠埛鏂�
    * @param {*} menuId     // 鑿滃崟Id
diff --git a/src/tabviews/custom/components/card/cardItem/index.jsx b/src/tabviews/custom/components/card/cardItem/index.jsx
index cc3c5e1..64f067d 100644
--- a/src/tabviews/custom/components/card/cardItem/index.jsx
+++ b/src/tabviews/custom/components/card/cardItem/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification } from 'antd'
 
@@ -81,29 +80,26 @@
       } else {
         MKEmitter.emit('modifyTabs', newtab, 'plus', true)
       }
-    } else if (card.setting.click === 'menu') {
-      let menu = null
+    } else if (card.setting.click === 'menu' && card.setting.menu) {
+      let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
-      if (card.setting.MenuID) {
-        let _menu = this.props.permMenus.filter(m => m.MenuID === card.setting.MenuID)[0] || ''
+      if (!menu && card.setting.MenuName && card.setting.tabType) {
         menu = {
-          MenuID: card.setting.MenuID,
-          MenuName: _menu ? _menu.MenuName : card.setting.MenuName,
-          MenuNo: card.setting.MenuNo,
-          type: _menu ? _menu.type : card.setting.tabType
+          MenuID: menuId,
+          MenuName: card.setting.MenuName,
+          MenuNo: card.setting.MenuNo || '',
+          type: card.setting.tabType
         }
-      } else if (card.setting.menu && card.setting.menu.length > 0) {
-        let menu_id = card.setting.menu.slice(-1)[0]
-        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+      }
 
-        if (!menu) {
-          notification.warning({
-            top: 92,
-            message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
-            duration: 5
-          })
-          return
-        }
+      if (!menu) {
+        notification.warning({
+          top: 92,
+          message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+          duration: 5
+        })
+        return
       }
 
       let newtab = {
@@ -175,14 +171,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(CardBoxComponent)
\ No newline at end of file
+export default CardBoxComponent
\ No newline at end of file
diff --git a/src/tabviews/custom/components/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index 34153e6..df3a4e9 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -9,8 +9,6 @@
 import asyncElementComponent from '@/utils/asyncComponent'
 import { getMark } from '@/utils/utils.js'
 import MkIcon from '@/components/mk-icon'
-import MKEmitter from '@/utils/events.js'
-import LostPng from '@/assets/img/lost.png'
 import Encrypts from '@/components/encrypts'
 import './index.scss'
 
@@ -29,6 +27,7 @@
 const QrCode = asyncElementComponent(() => import('@/components/qrcode'))
 const MkProgress = asyncElementComponent(() => import('@/components/mkProgress'))
 const Video = asyncComponent(() => import('@/components/video'))
+const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
 const PicRadio = {
   '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
   '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
@@ -555,26 +554,12 @@
         }
   
         let scale = url && card.scale === 'true'
-        let urls = url ? url.split(',').filter(Boolean) : [LostPng]
-  
-        if (!url) {
-          _imagestyle = {backgroundSize: 'contain'}
-        }
+        let urls = url ? url.split(',').filter(Boolean) : ['']
 
         urls.forEach((u, i) => {
           contents.push(<Col key={card.uuid + i} span={card.width}>
             <div style={_style} onClick={(e) => {this.openNewView(e, card)}}>
-              <div
-                className={'ant-mk-picture' + (scale ? ' scale' : '')}
-                onClick={(e) => {
-                  if (!scale) return
-
-                  e.stopPropagation()
-  
-                  MKEmitter.emit('mkImageScale', url, urls)
-                }}
-                style={{..._imagestyle, backgroundImage: `url('${u}')`}}
-              ></div>
+              <MkPicture style={_imagestyle} scale={scale} url={u} urls={urls}/>
             </div>
           </Col>)
         })
diff --git a/src/tabviews/custom/components/card/cardcellList/index.scss b/src/tabviews/custom/components/card/cardcellList/index.scss
index 2030460..fa2af83 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.scss
+++ b/src/tabviews/custom/components/card/cardcellList/index.scss
@@ -151,15 +151,6 @@
       }
     }
   }
-  .ant-mk-picture {
-    background-size: cover;
-    background-position: center center;
-    background-repeat: no-repeat;
-    background-color: #f5f5f5;
-  }
-  .ant-mk-picture.scale {
-    cursor: zoom-in;
-  }
   .ant-mk-icon {
     vertical-align: top;
     line-height: inherit;
diff --git a/src/tabviews/custom/components/card/prop-card/index.jsx b/src/tabviews/custom/components/card/prop-card/index.jsx
index 71a8068..4f4c46c 100644
--- a/src/tabviews/custom/components/card/prop-card/index.jsx
+++ b/src/tabviews/custom/components/card/prop-card/index.jsx
@@ -51,7 +51,7 @@
       BID = BData.$BID || ''
     }
     
-    if (_config.wrap.datatype !== 'static') {
+    if (_config.wrap.datatype === 'dynamic') {
       _sync = _config.setting.sync === 'true'
 
       if (_sync && data) {
@@ -67,6 +67,9 @@
         }
         _sync = false
       }
+    } else if (_config.wrap.datatype === 'public' && window.GLOB.CacheData.get(_config.wrap.publicId)) {
+      _data = window.GLOB.CacheData.get(_config.wrap.publicId)
+      _data = fromJS(_data).toJS()
     }
 
     _data.$$BID = BID || ''
@@ -122,10 +125,16 @@
       config: _config,
       arr_field: _config.columns.map(col => col.field).join(','),
     }, () => {
-      if (_config.wrap.datatype !== 'static' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
+      if (_config.wrap.datatype === 'dynamic' && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
         setTimeout(() => {
           this.loadData()
         }, _config.setting.delay || 0)
+      } else if (_config.wrap.datatype === 'public') {
+        if (_data.$$loaded && selected !== 'false') {
+          setTimeout(() => {
+            this.checkTopLine()
+          }, 200)
+        }
       } else if (!_sync && selected !== 'false') {
         setTimeout(() => {
           this.checkTopLine()
@@ -142,7 +151,11 @@
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
-    if (config.timer) {
+    if (config.wrap.datatype === 'public') {
+      MKEmitter.addListener('mkPublicData', this.mkPublicData)
+    }
+
+    if (config.timer && config.wrap.datatype === 'dynamic') {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {this.loadData(true)})
     }
@@ -157,6 +170,7 @@
       return
     }
     MKEmitter.removeListener('reloadData', this.reloadData)
+    MKEmitter.removeListener('mkPublicData', this.mkPublicData)
     MKEmitter.removeListener('resetSelectLine', this.resetParentParam)
     MKEmitter.removeListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.removeListener('refreshByButtonResult', this.refreshByButtonResult)
@@ -190,13 +204,33 @@
           }, 200)
         }
       })
-    } else if ( config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
+    } else if (config.setting.syncRefresh && nextProps.mainSearch && !is(fromJS(this.props.mainSearch), fromJS(nextProps.mainSearch))) {
       this.setState({}, () => {
         this.loadData()
       })
     }
   }
 
+  mkPublicData = (publicId, data) => {
+    const { config, selected, BID, BData } = this.state
+
+    if (config.wrap.datatype === 'public' && config.wrap.publicId === publicId) {
+      let _data = fromJS(data).toJS()
+
+      _data.$$BID = BID || ''
+      _data.$$BData = BData || ''
+      _data.$$uuid = _data[config.setting.primaryKey] || ''
+
+      this.setState({data: _data}, () => {
+        if (selected !== 'false') {
+          setTimeout(() => {
+            this.checkTopLine()
+          }, 200)
+        }
+      })
+    }
+  }
+
   checkTopLine = () => {
     const { config, data, selected } = this.state
 
diff --git a/src/tabviews/custom/components/card/table-card/index.jsx b/src/tabviews/custom/components/card/table-card/index.jsx
index 40dce07..f2616d8 100644
--- a/src/tabviews/custom/components/card/table-card/index.jsx
+++ b/src/tabviews/custom/components/card/table-card/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { Spin, notification, Row, Col, Empty, Pagination } from 'antd'
 import { DownOutlined } from '@ant-design/icons'
@@ -348,29 +347,26 @@
   }
 
   openView = (card, data) => {
-    if (card.setting.click === 'menu') {
-      let menu = null
+    if (card.setting.click === 'menu' && card.setting.menu) {
+      let menuId = card.setting.MenuID || card.setting.menu.slice(-1)[0]
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
-      if (card.setting.MenuID) {
-        let _menu = this.props.permMenus.filter(m => m.MenuID === card.setting.MenuID)[0] || ''
+      if (!menu && card.setting.MenuName && card.setting.tabType) {
         menu = {
-          MenuID: card.setting.MenuID,
-          MenuName: _menu ? _menu.MenuName : card.setting.MenuName,
-          MenuNo: card.setting.MenuNo,
-          type: _menu ? _menu.type : card.setting.tabType
+          MenuID: menuId,
+          MenuName: card.setting.MenuName,
+          MenuNo: card.setting.MenuNo || '',
+          type: card.setting.tabType
         }
-      } else if (card.setting.menu && card.setting.menu.length > 0) {
-        let menu_id = card.setting.menu.slice(-1)[0]
-        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+      }
 
-        if (!menu) {
-          notification.warning({
-            top: 92,
-            message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
-            duration: 5
-          })
-          return
-        }
+      if (!menu) {
+        notification.warning({
+          top: 92,
+          message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+          duration: 5
+        })
+        return
       }
 
       let newtab = {
@@ -496,14 +492,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(TableCard)
\ No newline at end of file
+export default TableCard
\ No newline at end of file
diff --git a/src/tabviews/custom/components/carousel/prop-card/index.jsx b/src/tabviews/custom/components/carousel/prop-card/index.jsx
index fc913f1..c5b37fe 100644
--- a/src/tabviews/custom/components/carousel/prop-card/index.jsx
+++ b/src/tabviews/custom/components/carousel/prop-card/index.jsx
@@ -48,7 +48,7 @@
       BID = BData.$BID || ''
     }
     
-    if (_config.setting && _config.wrap.datatype !== 'static') {
+    if (_config.setting && _config.wrap.datatype === 'dynamic') {
       _sync = _config.setting.sync === 'true'
 
       if (_sync && data) {
@@ -97,7 +97,7 @@
       config: _config,
       arr_field: _config.columns.map(col => col.field).join(','),
     }, () => {
-      if (_config.wrap.datatype !== 'static' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
+      if (_config.wrap.datatype === 'dynamic' && _config.setting && _config.setting.sync !== 'true' && _config.setting.onload === 'true') {
         setTimeout(() => {
           this.loadData()
         }, _config.setting.delay || 0)
@@ -113,7 +113,7 @@
     MKEmitter.addListener('queryModuleParam', this.queryModuleParam)
     MKEmitter.addListener('refreshByButtonResult', this.refreshByButtonResult)
 
-    if (config.timer) {
+    if (config.timer && config.wrap.datatype === 'dynamic') {
       this.timer = new TimerTask()
       this.timer.init(config.uuid, config.timer, config.timerRepeats, () => {
         this.loadData('timer')
diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx
index 06c4b42..8916b90 100644
--- a/src/tabviews/custom/components/chart/antv-pie/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -2,7 +2,6 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
-import { connect } from 'react-redux'
 import DataSet, { DataView } from '@antv/data-set'
 import { Spin, Empty, notification } from 'antd'
 import { DownloadOutlined } from '@ant-design/icons'
@@ -923,9 +922,10 @@
     
     if (plot.linkmenu && plot.linkmenu.length > 0) {
       let menu_id = plot.linkmenu.slice(-1)[0]
-      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
-
+      
       chart.on('element:dblclick', (ev) => {
+        let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
+
         if (!menu) {
           notification.warning({
             top: 92,
@@ -1042,14 +1042,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(PieChart)
\ No newline at end of file
+export default PieChart
\ No newline at end of file
diff --git a/src/tabviews/custom/components/form/simple-form/index.jsx b/src/tabviews/custom/components/form/simple-form/index.jsx
index 74d5900..5711995 100644
--- a/src/tabviews/custom/components/form/simple-form/index.jsx
+++ b/src/tabviews/custom/components/form/simple-form/index.jsx
@@ -1,7 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { connect } from 'react-redux'
 import { Spin, notification } from 'antd'
 
 import Api from '@/api'
@@ -196,7 +195,7 @@
   execSuccess = (btn, id) => {
     if (btn.linkmenu && btn.linkmenu.length > 0) {
       let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
-      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
 
       if (!menu) return
 
@@ -312,14 +311,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(SimpleForm)
\ No newline at end of file
+export default SimpleForm
\ No newline at end of file
diff --git a/src/tabviews/custom/components/form/step-form/index.jsx b/src/tabviews/custom/components/form/step-form/index.jsx
index c034d19..d942371 100644
--- a/src/tabviews/custom/components/form/step-form/index.jsx
+++ b/src/tabviews/custom/components/form/step-form/index.jsx
@@ -1,7 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { connect } from 'react-redux'
 import { Spin, notification, Button } from 'antd'
 
 import Api from '@/api'
@@ -245,7 +244,7 @@
 
     if (btn.linkmenu && btn.linkmenu.length > 0) {
       let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
-      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
 
       if (!menu) return
 
@@ -411,14 +410,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(StepForm)
\ No newline at end of file
+export default StepForm
\ No newline at end of file
diff --git a/src/tabviews/custom/components/form/tab-form/index.jsx b/src/tabviews/custom/components/form/tab-form/index.jsx
index fd0f2a1..870b4ad 100644
--- a/src/tabviews/custom/components/form/tab-form/index.jsx
+++ b/src/tabviews/custom/components/form/tab-form/index.jsx
@@ -1,7 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { connect } from 'react-redux'
 import { Spin, notification } from 'antd'
 
 import Api from '@/api'
@@ -206,7 +205,7 @@
   execSuccess = (btn, id) => {
     if (btn.linkmenu && btn.linkmenu.length > 0) {
       let menu_id = btn.linkmenu[btn.linkmenu.length - 1]
-      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
 
       if (!menu) return
 
@@ -336,14 +335,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(TabForm)
\ No newline at end of file
+export default TabForm
\ No newline at end of file
diff --git a/src/tabviews/custom/components/interfaces/index.jsx b/src/tabviews/custom/components/interfaces/index.jsx
new file mode 100644
index 0000000..166f72b
--- /dev/null
+++ b/src/tabviews/custom/components/interfaces/index.jsx
@@ -0,0 +1,37 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+
+import MkInterItem from './interItem'
+// import './index.scss'
+
+class MkInterfaces extends Component {
+  static propTpyes = {
+    BID: PropTypes.any,
+    interfaces: PropTypes.array
+  }
+
+  state = {}
+
+  shouldComponentUpdate (nextProps, nextState) { return false }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { interfaces, BID } = this.props
+
+    return (
+      <>
+        {interfaces.map(m => <MkInterItem key={m.uuid} config={m} BID={BID}/>)}
+      </>
+    )
+  }
+}
+
+export default MkInterfaces
\ No newline at end of file
diff --git a/src/tabviews/custom/components/interfaces/index.scss b/src/tabviews/custom/components/interfaces/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tabviews/custom/components/interfaces/index.scss
diff --git a/src/tabviews/custom/components/interfaces/interItem/index.jsx b/src/tabviews/custom/components/interfaces/interItem/index.jsx
new file mode 100644
index 0000000..1cf8c19
--- /dev/null
+++ b/src/tabviews/custom/components/interfaces/interItem/index.jsx
@@ -0,0 +1,73 @@
+import {Component} from 'react'
+import PropTypes from 'prop-types'
+import { notification } from 'antd'
+
+import Api from '@/api'
+import UtilsDM from '@/utils/utils-datamanage.js'
+import MKEmitter from '@/utils/events.js'
+import TimerTask from '@/utils/timer-task.js'
+
+// import './index.scss'
+
+class MkInterItem extends Component {
+  static propTpyes = {
+    BID: PropTypes.any,        // 涓婄骇涓婚敭鍊�
+    config: PropTypes.object,  // 閰嶇疆淇℃伅
+  }
+
+  state = {}
+
+  componentDidMount () {
+    const { config } = this.props
+
+    if (config.setting.timer) {
+      this.timer = new TimerTask()
+      this.timer.init(config.uuid, config.setting.timer, config.setting.timerRepeats, () => {this.loadData()})
+    }
+    setTimeout(() => {
+      this.loadData()
+    }, config.setting.delay)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) { return false }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    this.timer && this.timer.stop()
+  }
+
+  async loadData () {
+    const { config, BID } = this.props
+
+    let param = UtilsDM.getQueryDataParams(config.setting, config.columns.map(col => col.field).join(','), [], config.setting.order, 1, 1, BID)
+
+    let result = await Api.genericInterface(param)
+    if (result.status) {
+      let _data = { $$empty: true }
+
+      if (result.data && result.data[0]) {
+        _data = result.data[0]
+      }
+      
+      _data.$$loaded = true
+
+      MKEmitter.emit('mkPublicData', config.uuid, _data)
+    } else {
+      this.timer && this.timer.stop()
+      notification.error({
+        top: 92,
+        message: result.message,
+        duration: 10
+      })
+    }
+  }
+
+  render() {return null}
+}
+
+export default MkInterItem
\ No newline at end of file
diff --git a/src/tabviews/custom/components/interfaces/interItem/index.scss b/src/tabviews/custom/components/interfaces/interItem/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tabviews/custom/components/interfaces/interItem/index.scss
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 317b96d..0e98c31 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -16,6 +16,7 @@
 
 const { Paragraph } = Typography
 const CardCellComponent = asyncComponent(() => import('@/tabviews/custom/components/card/cardcellList'))
+const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
 const PicRadio = {
   '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
   '5:1': '20%', '6:1': '16.67%', '7:1': '14.29%', '8:1': '12.5%', '9:1': '11.11%',
@@ -253,10 +254,7 @@
         <div>
           {photos.map((url, i) => (
             <Col key={i} span={col.span || 24}>
-              <div className={'ant-mk-picture' + (scale ? ' scale' : '')} onClick={() => {
-                if (!scale) return
-                MKEmitter.emit('mkImageScale', url, photos)
-              }} style={{paddingTop, backgroundImage: `url('${url}')`}}></div>
+              <MkPicture style={{paddingTop}} scale={scale} url={url} urls={photos}/>
             </Col>
           ))}
         </div>
diff --git a/src/tabviews/custom/components/share/normalTable/index.scss b/src/tabviews/custom/components/share/normalTable/index.scss
index ebaa748..697e60e 100644
--- a/src/tabviews/custom/components/share/normalTable/index.scss
+++ b/src/tabviews/custom/components/share/normalTable/index.scss
@@ -98,14 +98,7 @@
         }
         .ant-mk-picture {
           position: relative;
-          background-position: center center;
-          background-size: cover;
-          background-repeat: no-repeat;
-          background-color: #f5f5f5;
           margin: 2px;
-        }
-        .ant-mk-picture.scale {
-          cursor: zoom-in;
         }
         .action-col {
           .ant-btn > .anticon + span {
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 8651b50..f9ece5a 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -893,7 +893,7 @@
   static propTpyes = {
     statFValue: PropTypes.any,       // 鍚堣瀛楁鏁版嵁
     MenuID: PropTypes.string,        // 鑿滃崟Id
-    setting: PropTypes.object,       // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乧olumnfixed锛堝垪鍥哄畾锛夈�乤ctionfixed锛堟寜閽浐瀹氾級
+    setting: PropTypes.object,       // 琛ㄦ牸鍏ㄥ眬璁剧疆锛歵ableType锛堣〃鏍兼槸鍚﹀彲閫夈�佸崟閫夈�佸閫夛級銆乤ctionfixed锛堟寜閽浐瀹氾級
     columns: PropTypes.array,        // 琛ㄦ牸鍒�
     lineMarks: PropTypes.any,        // 琛屾爣璁�
     fields: PropTypes.array,         // 缁勪欢瀛楁闆�
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 4e5b652..971228d 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.scss
@@ -74,17 +74,6 @@
         .card-cell-list {
           color: rgba(0, 0, 0, 0.85);
         }
-        .ant-mk-picture {
-          position: relative;
-          background-position: center center;
-          background-size: cover;
-          background-repeat: no-repeat;
-          background-color: #f5f5f5;
-          margin: 2px;
-        }
-        .ant-mk-picture.scale {
-          cursor: zoom-in;
-        }
         .action-col {
           .ant-btn > .anticon + span {
             margin-left: 3px;
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index 6f41f64..2f6eafe 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -1,15 +1,13 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Row, Col } from 'antd'
 
 import Api from '@/api'
-import options from '@/store/options.js'
 import zhCN from '@/locales/zh-CN/main.js'
 import enUS from '@/locales/en-US/main.js'
 import Utils from '@/utils/utils.js'
-import UtilsDM, { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
+import { getStructuredParams, getStructDefaultParam } from '@/utils/utils-datamanage.js'
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
 import NotFount from '@/components/404'
@@ -42,6 +40,8 @@
 const CustomChart = asyncComponent(() => import('./components/chart/custom-chart'))
 const TimeLine = asyncComponent(() => import('./components/timeline/normal-timeline'))
 const Voucher = asyncComponent(() => import('./components/module/voucher'))
+const DebugTable = asyncComponent(() => import('@/tabviews/debugtable'))
+const MkInterfaces = asyncComponent(() => import('@/tabviews/custom/components/interfaces'))
 
 class CustomPage extends Component {
   static propTpyes = {
@@ -65,7 +65,6 @@
     data: null,           // 鍒楄〃鏁版嵁闆�
     loading: false,       // 鍒楄〃鏁版嵁鍔犺浇涓�
     visible: false,       // 鏍囩椤垫帶鍒�
-    treevisible: false,   // 鑿滃崟缁撴瀯鏍戝脊妗嗘樉绀洪殣钘忔帶鍒�
     shortcuts: null       // 蹇嵎閿�
   }
 
@@ -73,7 +72,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, MenuID } = this.props
+    const { MenuID } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -144,35 +143,6 @@
 
       window.GLOB.CacheData.set(MenuID, param)
 
-      config.components = this.filterComponent(config.components, roleId, permAction, balMap, skip, param, MenuID)
-      
-      // 鑾峰彇涓绘悳绱㈡潯浠�
-      let mainSearch = []
-      config.components.forEach(component => {
-        if (component.type !== 'search') return
-
-        component.search = component.search.map(item => {
-          item.oriInitval = item.initval
-          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
-            item.initval = param.$searchval
-          }
-
-          return item
-        })
-
-        mainSearch = Utils.initMainSearch(component.search)
-      })
-
-      let params = []
-      let BID = param.$BID || ''
-      let inherit = {}
-
-      if (config.cacheUseful === 'true') { // 缂撳瓨缁ф壙
-        inherit.cacheUseful = config.cacheUseful
-        inherit.timeUnit = config.timeUnit
-        inherit.cacheTime = config.cacheTime
-      }
-
       let userName = sessionStorage.getItem('User_Name') || ''
       let fullName = sessionStorage.getItem('Full_Name') || ''
 
@@ -202,6 +172,37 @@
         })
       }
 
+      config.interfaces = this.formatInterSetting(config.interfaces, regs)
+
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, param, MenuID, config.interfaces)
+      
+      // 鑾峰彇涓绘悳绱㈡潯浠�
+      let mainSearch = []
+      config.components.forEach(component => {
+        if (component.type !== 'search') return
+
+        component.search = component.search.map(item => {
+          item.oriInitval = item.initval
+          if (['text', 'select', 'link'].includes(item.type) && param.$searchkey === item.field) {
+            item.initval = param.$searchval
+          }
+
+          return item
+        })
+
+        mainSearch = Utils.initMainSearch(component.search)
+      })
+
+      let params = []
+      let BID = param.$BID || ''
+      let inherit = {}
+
+      if (config.cacheUseful === 'true') { // 缂撳瓨缁ф壙
+        inherit.cacheUseful = config.cacheUseful
+        inherit.timeUnit = config.timeUnit
+        inherit.cacheTime = config.cacheTime
+      }
+
       config.components = this.formatSetting(config.components, params, mainSearch, inherit, regs, balMap)
 
       if ([...balMap.keys()].length > 0) {
@@ -210,11 +211,11 @@
 
       this.setState({
         BID: BID,
-        shortcuts,
+        shortcuts: shortcuts.length > 0 ? shortcuts : null,
         config,
         mainSearch
       }, () => {
-        if (!params || params.length === 0) {
+        if (params.length === 0) {
           setTimeout(() => { // 寤舵椂鍔犺浇鐘舵��
             this.setState({
               loadingview: false
@@ -227,8 +228,6 @@
         if (!this.props.Tab) {
           this.setShortcut()
         }
-
-        this.loadData()
       })
     } else {
       this.setState({
@@ -246,11 +245,6 @@
   setShortcut = () => {
     const { shortcuts } = this.state
 
-    if (!shortcuts || shortcuts.length === 0) {
-      document.onkeydown = () => {}
-      return
-    }
-
     document.onkeydown = (event) => {
       let e = event || window.event
       let keyCode = e.keyCode || e.which || e.charCode
@@ -265,8 +259,18 @@
       }
 
       if (!preKey || !keyCode) return
-
+      
       let _shortcut = `${preKey}+${keyCode}`
+
+      if (window.GLOB.breakpoint && _shortcut === 'ctrl+67') {
+        window.debugger = false
+        window.GLOB.breakpoint = false
+        sessionStorage.removeItem('breakpoint')
+        
+        MKEmitter.emit('debugChange')
+      }
+
+      if (!shortcuts) return
 
       shortcuts.some(item => {
         if (item.$shortcut === _shortcut) {
@@ -278,176 +282,7 @@
     }
   }
 
-  loadData = () => {
-    const { config } = this.state
-
-    if (!config.interfaces || config.interfaces.length === 0) return
-
-    let inters = []
-
-    config.interfaces.forEach(item => {
-      if (item.status !== 'true') return
-
-      if (window.GLOB.systemType === 'production' && !item.proInterface) {
-        notification.warning({
-          top: 92,
-          message: `銆�${item.name}銆嬫湭璁剧疆姝e紡绯荤粺鍦板潃!`,
-          duration: 3
-        })
-        return
-      }
-
-      item.MenuName = config.MenuName || ''
-
-      inters.push(item)
-    })
-    
-    if (inters.length > 0) {
-      this.loadOutResource(inters)
-    }
-  }
-
-  loadOutResource = (inters) => {
-    let setting = inters.shift()
-    let param = UtilsDM.getPrevQueryParams(setting, [], this.state.BID)
-
-    Api.genericInterface(param).then(res => {
-      if (res.status) {
-        if (res.mk_ex_invoke === 'false' || res.mk_ex_invoke === false) {
-          if (inters.length > 0) {
-            this.loadOutResource(inters)
-          }
-        } else {
-          this.customOuterRequest(res, setting, inters)
-        }
-      } else {
-        notification.error({
-          top: 92,
-          message: res.message,
-          duration: 10
-        })
-      }
-    })
-  }
-
-  customOuterRequest = (result, setting, inters) => {
-    let url = ''
-
-    if (window.GLOB.systemType === 'production') {
-      url = setting.proInterface
-    } else {
-      url = setting.interface
-    }
-
-    let mkey = result.mk_api_key || ''
-
-    delete result.mk_ex_invoke
-    delete result.status
-    delete result.message
-    delete result.ErrCode
-    delete result.ErrMesg
-    delete result.mk_api_key
-
-    let param = {}
-
-    Object.keys(result).forEach(key => {
-      key = key.replace(/^mk_/ig, '')
-      param[key] = result[key]
-    })
-
-    Api.directRequest(url, setting.method, param, setting.cross).then(res => {
-      if (typeof(res) !== 'object') {
-        let error = '鏈煡鐨勮繑鍥炵粨鏋滐紒'
-
-        if (typeof(res) === 'string') {
-          error = res.replace(/'/ig, '"')
-        }
-
-        let _result = {
-          mk_api_key: mkey,
-          $ErrCode: 'E',
-          $ErrMesg: error
-        }
-
-        this.customCallbackRequest(_result, setting, inters)
-      } else {
-        if (Array.isArray(res)) {
-          res = { data: res }
-        }
-        res.mk_api_key = mkey
-        this.customCallbackRequest(res, setting, inters)
-      }
-    }, (e) => {
-      let _result = {
-        mk_api_key: mkey,
-        $ErrCode: 'E',
-        $ErrMesg: e && e.statusText ? e.statusText : ''
-      }
-
-      this.customCallbackRequest(_result, setting, inters)
-    })
-  }
-
-  customCallbackRequest = (result, setting, inters) => {
-    let errSql = ''
-    if (result.$ErrCode === 'E') {
-      errSql = `
-        set @ErrorCode='E'
-        set @retmsg='${result.$ErrMesg}'
-      `
-      delete result.$ErrCode
-      delete result.$ErrMesg
-    }
-
-    let lines = UtilsDM.getCallBackSql(setting, result)
-    let param = {}
-
-    if (setting.callbackType === 'script') { // 浣跨敤鑷畾涔夎剼鏈�
-      let sql = lines.map(item => (`
-        ${item.insert}
-        ${item.selects.join(` union all
-        `)}
-      `))
-      sql = sql.join('')
-      
-      param = UtilsDM.getCallBackQueryParams(setting, sql, errSql, this.state.BID)
-    } else {
-      param.func = 's_ex_result_back'
-      param.s_ex_result = lines.map((item, index) => ({
-        MenuID: this.props.MenuID || '',
-        MenuName: this.props.MenuName || '',
-        TableName: item.table,
-        LongText: window.btoa(window.encodeURIComponent(`${item.insert}  ${item.selects.join(` union all `)}`)),
-        Sort: index + 1
-      }))
-
-      if (window.GLOB.debugger === true || (window.debugger === true && options.sysType !== 'cloud')) {
-        let sql = lines.map(item => (`
-          ${item.insert}
-          ${item.selects.join(` union all
-          `)}
-        `))
-        sql = sql.join('')
-        console.info(sql.replace(/\n\s{10}/ig, '\n'))
-      }
-    }
-
-    Api.genericInterface(param).then(res => {
-      if (res.status) {
-        if (inters.length > 0) {
-          this.loadOutResource(inters)
-        }
-      } else {
-        notification.error({
-          top: 92,
-          message: res.message,
-          duration: 10
-        })
-      }
-    })
-  }
-
-  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId) => {
+  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces) => {
     return components.filter(item => {
       item.$pageId = pageId
       
@@ -533,7 +368,7 @@
         item.subtabs = item.subtabs.map(tab => {
           tab.$pageId = pageId
 
-          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId)
+          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces)
           return tab
         })
 
@@ -546,7 +381,7 @@
           return false
         }
 
-        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId)
+        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces)
 
         return true
       } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart'].includes(item.type)) {
@@ -562,6 +397,15 @@
           item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
         ) {
           return false
+        }
+
+        if (item.wrap.datatype === 'public') {
+          let inter = interfaces.filter(int => item.wrap.publicId === int.uuid)[0]
+          if (!inter) {
+            item.wrap.datatype = 'static'
+          } else {
+            item.setting = inter.setting
+          }
         }
       }
 
@@ -617,7 +461,7 @@
       
             if (col.linkmenu && col.linkmenu.length > 0) {
               let menu_id = col.linkmenu.pop()
-              col.linkThdMenu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+              col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
             } else {
               col.linkThdMenu = ''
             }
@@ -996,6 +840,8 @@
         component.components = this.formatSetting(component.components, null, null, inherit, regs, balMap)
         component = {...component, ...inherit}
         return component
+      } else if (component.wrap && component.wrap.datatype === 'public') {
+        return component
       }
 
       if (component.setting) {
@@ -1092,6 +938,61 @@
     })
   }
 
+  // 鏍煎紡鍖栭粯璁よ缃�
+  formatInterSetting = (inters, regs) => {
+    if (!inters) return []
+
+    let interfaces = inters.filter(m => m.status === 'true')
+
+    let delay = 15
+    return interfaces.map(inter => {
+      inter.setting.delay = delay
+      delay += 15
+
+      if (inter.setting.interType !== 'system') return inter
+
+      let _customScript = ''
+      inter.scripts.forEach(script => {
+        if (script.status !== 'false') {
+          _customScript += `
+          ${script.sql}
+          `
+        }
+      })
+      delete inter.scripts
+
+      inter.setting.$name = '鍏叡鏁版嵁婧�-' + inter.setting.name
+      inter.setting.execute = inter.setting.execute !== 'false'
+      inter.setting.laypage = true
+
+      if (!inter.setting.execute) {
+        inter.setting.dataresource = ''
+      }
+      if (/\s/.test(inter.setting.dataresource)) {
+        inter.setting.dataresource = '(' + inter.setting.dataresource + ') tb'
+      }
+  
+      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+        inter.setting.dataresource = inter.setting.dataresource.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
+        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$/ig, '*/')
+        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@datam@/ig, '\'Y\'')
+        _customScript = _customScript.replace(/@\$/ig, '*/')
+      } else {
+        inter.setting.dataresource = inter.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+      }
+
+      regs.forEach(cell => {
+        inter.setting.dataresource = inter.setting.dataresource.replace(cell.reg, cell.value)
+        _customScript = _customScript.replace(cell.reg, cell.value)
+      })
+
+      inter.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+
+      return inter
+    })
+  }
+
   /**
    * @description 涓昏〃鏁版嵁鍔犺浇
    */ 
@@ -1151,6 +1052,7 @@
   }
 
   componentDidMount () {
+    MKEmitter.addListener('debugChange', this.debugChange)
     MKEmitter.addListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.addListener('resetActiveMenu', this.resetActiveMenu)
   }
@@ -1162,11 +1064,21 @@
     this.setState = () => {
       return
     }
+    MKEmitter.removeListener('debugChange', this.debugChange)
     MKEmitter.removeListener('reloadMenuView', this.reloadMenuView)
     MKEmitter.removeListener('resetActiveMenu', this.resetActiveMenu)
 
     window.GLOB.CacheData.delete(this.props.MenuID)
-    this.deleteCache(this.state.config.components)
+    if (this.state.config) {
+      this.deleteCache(this.state.config.components)
+      this.state.config.interfaces.forEach(m => {
+        window.GLOB.CacheData.delete(m.uuid)
+      })
+    }
+  }
+
+  debugChange = () => {
+    this.setState({visible: !this.state.visible})
   }
 
   deleteCache = (components) => {
@@ -1360,30 +1272,20 @@
   }
 
   render() {
-    const { loadingview, viewlost, config, loading, shortcuts } = this.state
+    const { loadingview, viewlost, config, loading, shortcuts, BID } = this.state
 
     return (
       <div className={'custom-page-wrap ' + (loadingview || loading ? 'loading' : '')} id={this.state.ContainerId} style={config ? config.style : null}>
         {(loadingview || loading) ? <Spin className="view-spin" size="large" /> : null}
         <Row className="component-wrap">{this.getComponents()}</Row>
+        {config && config.interfaces.length > 0 ? <MkInterfaces BID={BID} interfaces={config.interfaces}/> : null}
+        {config && window.GLOB.breakpoint ? <DebugTable /> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
+        {!window.GLOB.mkHS && config ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts || []}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    refreshTab: state.refreshTab,
-    permAction: state.permAction,
-    permMenus: state.permMenus
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(CustomPage)
\ No newline at end of file
+export default CustomPage
\ No newline at end of file
diff --git a/src/tabviews/debugtable/index.jsx b/src/tabviews/debugtable/index.jsx
new file mode 100644
index 0000000..b6833f5
--- /dev/null
+++ b/src/tabviews/debugtable/index.jsx
@@ -0,0 +1,117 @@
+import React, {Component} from 'react'
+import { is, fromJS } from 'immutable'
+import { notification, Table} from 'antd'
+import { RedoOutlined } from '@ant-design/icons'
+
+import Api from '@/api'
+import MKEmitter from '@/utils/events.js'
+import UtilsDM from '@/utils/utils-datamanage.js'
+
+import './index.scss'
+
+class DebugTable extends Component {
+  state = {
+    columns: [
+      {align: 'left', dataIndex: 'Sort', sorter: false, title: 'Sort', width: 120},
+      {align: 'left', dataIndex: 'CDefine1', sorter: false, title: '鏂囨湰1', width: 120},
+      {align: 'left', dataIndex: 'CDefine2', sorter: false, title: '鏂囨湰2', width: 120},
+      {align: 'left', dataIndex: 'CDefine3', sorter: false, title: '鏂囨湰3', width: 120},
+      {align: 'left', dataIndex: 'CDefine4', sorter: false, title: '鏂囨湰4', width: 120},
+      {align: 'left', dataIndex: 'CDefine5', sorter: false, title: '鏂囨湰5', width: 120},
+      {align: 'left', dataIndex: 'CDefine6', sorter: false, title: '鏂囨湰6', width: 120},
+      {align: 'left', dataIndex: 'CDefine7', sorter: false, title: '鏂囨湰7', width: 120},
+    ],
+    data: [],
+    loading: false,
+    setting: {
+      interType: 'system',
+      execute: true,
+      dataresource: '(select * from s_debug_value_log where createuserid=@userid@) tb'
+    },
+    arr_field: 'ID,Sort,CDefine1,CDefine2,CDefine3,CDefine4,CDefine5,CDefine6,CDefine7'
+  }
+
+  /**
+   * @description 瀛愯〃鏁版嵁鍔犺浇
+   */
+  async loadmaindata () {
+    const { setting, arr_field } = this.state
+
+    this.setState({
+      loading: true
+    })
+
+    let param = UtilsDM.getQueryDataParams(setting, arr_field, [], 'sort', 1, 9999, '')
+
+    let result = await Api.genericInterface(param)
+
+    if (result.status) {
+      let start = 1
+
+      this.setState({
+        data: result.data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item.ID || ''
+          item.$Index = start + index + ''
+
+          return item
+        }),
+        loading: false
+      })
+    } else {
+      this.setState({
+        loading: false
+      })
+
+      notification.error({
+        top: 92,
+        message: result.message,
+        duration: 10
+      })
+    }
+  }
+
+  refreshDebugTable = () => {
+    const { loading } = this.state
+
+    if (!loading) {
+      this.loadmaindata()
+    }
+  }
+
+  UNSAFE_componentWillMount() {
+    // 缁勪欢鍔犺浇鏃讹紝鑾峰彇鑿滃崟鏁版嵁
+    this.loadmaindata()
+  }
+
+  componentDidMount() {
+    MKEmitter.addListener('refreshDebugTable', this.refreshDebugTable)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('refreshDebugTable', this.refreshDebugTable)
+  }
+
+  render() {
+    const { data, loading, columns } = this.state
+
+    return (
+      <div className="debugtable">
+        <RedoOutlined className="mk-debug-reload" onClick={() => this.loadmaindata()}/>
+        <Table size="middle" columns={columns} dataSource={data} pagination={false} loading={loading} scroll={{ x: '100%', y: false }}/>
+      </div>
+    )
+  }
+}
+
+export default DebugTable
\ No newline at end of file
diff --git a/src/tabviews/debugtable/index.scss b/src/tabviews/debugtable/index.scss
new file mode 100644
index 0000000..773c2c0
--- /dev/null
+++ b/src/tabviews/debugtable/index.scss
@@ -0,0 +1,14 @@
+.debugtable {
+  position: relative;
+  min-height: 200px;
+  margin: 20px;
+
+  .mk-debug-reload {
+    color: var(--mk-sys-color);
+    position: absolute;
+    z-index: 1;
+    top: 5px;
+    right: 10px;
+    font-size: 16px;
+  }
+}
diff --git a/src/tabviews/formtab/index.jsx b/src/tabviews/formtab/index.jsx
index 3ff7443..339e762 100644
--- a/src/tabviews/formtab/index.jsx
+++ b/src/tabviews/formtab/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Tabs} from 'antd'
 import moment from 'moment'
@@ -48,7 +47,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, MenuID } = this.props
+    const { MenuID } = this.props
 
     let param = {
       func: 'sPC_Get_LongParam',
@@ -104,13 +103,13 @@
       }
 
       if (!window.GLOB.mkHS) {
-        config.action = config.action.filter(item => permAction[item.uuid])
+        config.action = config.action.filter(item => window.GLOB.mkActions[item.uuid])
         config.tabgroups.forEach(group => {
           group.sublist = group.sublist.filter(tab => {
             if (tab.supMenu === 'mainTable') {
               tab.supMenu = MenuID
             }
-            return permAction[tab.linkTab]
+            return window.GLOB.mkActions[tab.linkTab]
           })
         })
       } else {
@@ -669,14 +668,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NormalTable)
\ No newline at end of file
+export default NormalTable
\ No newline at end of file
diff --git a/src/tabviews/home/index.jsx b/src/tabviews/home/index.jsx
index ae14a8f..f79eb7e 100644
--- a/src/tabviews/home/index.jsx
+++ b/src/tabviews/home/index.jsx
@@ -1,10 +1,10 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
 import { notification, Spin } from 'antd'
 
 import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
+import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 const DefaultHome = asyncComponent(() => import('./defaulthome'))
@@ -18,25 +18,50 @@
   state = {
     loading: true,
     background: sessionStorage.getItem('home_background'),
-    waiting: true,
+    waitMenu: true,
+    waitAction: true,
     view: ''
   }
 
   componentDidMount () {
     this.loadHomeConfig()
-    if (this.props.permMenus.length > 0 && JSON.stringify(this.props.permAction) !== '{}') {
+    if (window.GLOB.mkThdMenus.length > 0) {
       this.setState({
-        waiting: false
+        waitMenu: false
       })
+    } else {
+      MKEmitter.addListener('mkMenuLoaded', this.mkMenuLoaded)
+    }
+    if (window.GLOB.mkActions.loaded) {
+      this.setState({
+        waitAction: false
+      })
+    } else {
+      MKEmitter.addListener('mkActionLoaded', this.mkActionLoaded)
     }
   }
 
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (nextProps.permMenus.length > 0 && JSON.stringify(nextProps.permAction) !== '{}') {
-      this.setState({
-        waiting: false
-      })
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
     }
+    MKEmitter.removeListener('mkMenuLoaded', this.mkMenuLoaded)
+    MKEmitter.removeListener('mkActionLoaded', this.mkActionLoaded)
+  }
+
+  mkMenuLoaded = () => {
+    this.setState({
+      waitMenu: false
+    })
+  }
+
+  mkActionLoaded = () => {
+    this.setState({
+      waitAction: false
+    })
   }
 
   loadHomeConfig = () => {
@@ -54,7 +79,8 @@
         } else {
           this.setState({
             loading: false,
-            waiting: false,
+            waitMenu: false,
+            waitAction: false,
             view: 'default'
           })
         }
@@ -73,9 +99,9 @@
   }
 
   render() {
-    const { loading, waiting, view, background } = this.state
+    const { loading, waitAction, waitMenu, view, background } = this.state
 
-    if (loading || waiting) {
+    if (loading || waitAction || waitMenu) {
       return (<div className="home-loading-view" style={{background: background}}><Spin className="home-box-spin" size="large" /></div>)
     } else if (view === 'custom') {
       return (<CustomPage MenuID={this.props.MenuID} MenuName="棣栭〉"/>)
@@ -85,15 +111,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction,
-    permMenus: state.permMenus
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(Home)
\ No newline at end of file
+export default Home
\ No newline at end of file
diff --git a/src/tabviews/subtable/index.jsx b/src/tabviews/subtable/index.jsx
index bc460d3..7725c16 100644
--- a/src/tabviews/subtable/index.jsx
+++ b/src/tabviews/subtable/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Switch, Row, Col, Tabs} from 'antd'
 
@@ -84,7 +83,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, permMenus, Tab } = this.props
+    const { Tab } = this.props
 
     let param = {
       func: 'sPC_Get_LongParam',
@@ -134,7 +133,7 @@
 
       // 鏉冮檺杩囨护
       if (!window.GLOB.mkHS) {
-        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
+        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
       } else {
         config.action = config.action.filter(item => item.hidden !== 'true')
       }
@@ -183,7 +182,7 @@
 
           if (col.linkmenu && col.linkmenu.length > 0) {
             let menu_id = col.linkmenu.slice(-1)[0]
-            col.linkThdMenu = permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+            col.linkThdMenu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menu_id)[0] || ''
           } else {
             col.linkThdMenu = ''
           }
@@ -1129,15 +1128,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction,
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(SubTabViewTable)
\ No newline at end of file
+export default SubTabViewTable
\ No newline at end of file
diff --git a/src/tabviews/subtabtable/index.jsx b/src/tabviews/subtabtable/index.jsx
index 9b576d2..6a11de2 100644
--- a/src/tabviews/subtabtable/index.jsx
+++ b/src/tabviews/subtabtable/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin} from 'antd'
 
@@ -61,7 +60,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, Tab } = this.props
+    const { Tab } = this.props
 
     let param = {
       func: 'sPC_Get_LongParam',
@@ -129,7 +128,7 @@
 
       // 鏉冮檺杩囨护
       if (!window.GLOB.mkHS) {
-        config.action = config.action.filter(item => item.hidden !== 'true' && permAction[item.uuid])
+        config.action = config.action.filter(item => item.hidden !== 'true' && window.GLOB.mkActions[item.uuid])
       } else {
         config.action = config.action.filter(item => item.hidden !== 'true')
       }
@@ -891,14 +890,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(SubTabModalTable)
\ No newline at end of file
+export default SubTabModalTable
\ No newline at end of file
diff --git a/src/tabviews/treepage/index.jsx b/src/tabviews/treepage/index.jsx
index f68831b..a173c8a 100644
--- a/src/tabviews/treepage/index.jsx
+++ b/src/tabviews/treepage/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { notification, Spin, Tabs, Tree, Row, Col, Card, Input, Empty } from 'antd'
 import { FolderOpenOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons'
@@ -59,7 +58,7 @@
    * @description 鑾峰彇椤甸潰閰嶇疆淇℃伅
    */
   async loadconfig () {
-    const { permAction, param, MenuName, MenuID } = this.props
+    const { param, MenuName, MenuID } = this.props
 
     let _param = {
       func: 'sPC_Get_LongParam',
@@ -123,7 +122,7 @@
           if (tab.supMenu === 'mainTable') {
             tab.supMenu = MenuID
           }
-          return permAction[tab.linkTab]}
+          return window.GLOB.mkActions[tab.linkTab]}
         )
       })
 
@@ -632,21 +631,11 @@
           </Col>
         </Row> : null}
         {!window.GLOB.mkHS && window.GLOB.systemType !== 'production' ? <PagemsgComponent menu={{MenuName: this.props.MenuName, MenuNo: this.props.MenuNo}} config={config} dict={this.state.dict} /> : null}
-        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts} permAction={this.props.permAction}/> : null}
+        {!window.GLOB.mkHS && shortcuts ? <SettingComponent config={config} dict={this.state.dict} shortcuts={shortcuts}/> : null}
         {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
       </div>
     )
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permAction: state.permAction
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(TreePage)
\ No newline at end of file
+export default TreePage
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index 2126df5..a4a4f03 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -376,7 +376,6 @@
         
         let item = {
           type: type,
-          readonly: false,
           readin: true,
           writein: true,
           fieldlen: fieldlen,
@@ -555,6 +554,10 @@
         this.setState({checkParam: check_param})
       }
 
+      if (window.GLOB.breakpoint) {
+        param.func = 'sPC_TableData_InUpDe_debug'
+      }
+
       _params.push(param)
     } else if (btn.Ot === 'required') {
       _params = data.map((cell, index) => {
@@ -672,6 +675,10 @@
           param.s_debug_type = 'Y'
         }
 
+        if (window.GLOB.breakpoint) {
+          param.func = 'sPC_TableData_InUpDe_debug'
+        }
+
         return param
       })
     }
@@ -775,7 +782,7 @@
   /**
    * @description 鑾峰彇鍥炶皟鑴氭湰鐨勫瓧娈靛畾涔�
    */
-  getSysDeclareSql = (btn, formdata, data, columns, primaryId, BID) => {
+  getSysDeclareSql = (btn, formdata, data, columns, primaryId, BID = '') => {
     let datavars = {}                 // 澹版槑鐨勫彉閲忥紝琛ㄥ崟鍙婃樉绀哄垪
     // 闇�瑕佸0鏄庣殑鍙橀噺闆�
     let _vars = ['tbid', 'errorcode', 'retmsg', 'billcode', 'bvoucher', 'fibvoucherdate', 'fiyear', 'username', 'fullname', 'modulardetailcode', 'roleid', 'mk_departmentcode', 'mk_organization', 'mk_user_type', 'mk_nation', 'mk_province', 'mk_city', 'mk_district', 'mk_address', 'bid']
@@ -798,14 +805,11 @@
   
         if (form.type === 'number' || form.type === 'rate') {
           let val = form.value
-          if (typeof(val) !== 'number') {
-            val = parseFloat(val)
-            if (isNaN(val)) {
-              val = 0
-            }
+          if (isNaN(val)) {
+            val = 0
           }
           _initFormfields.push(`@${_key}=${val}`)
-        } else if (['date', 'datemonth', 'datetime'].includes(form.type)) {
+        } else if (['date', 'datemonth'].includes(form.type)) {
           _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
         } else {
           _initFormfields.push(`@${_key}='${form.value}'`)
@@ -840,7 +844,7 @@
     }
   
     // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
-    if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') {
+    if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce' && columns && columns.length > 0) {
       datavars = {...data, ...datavars}
   
       const setField = (col) => {
@@ -882,17 +886,15 @@
         }
       }
   
-      if (columns && columns.length > 0) {
-        columns.forEach(col => {
-          if (col.type === 'colspan' || col.type === 'old_colspan') {
-            col.subcols.forEach(cell => {
-              setField(cell)
-            })
-          } else {
-            setField(col)
-          }
-        })
-      }
+      columns.forEach(col => {
+        if (col.type === 'colspan' || col.type === 'old_colspan') {
+          col.subcols.forEach(cell => {
+            setField(cell)
+          })
+        } else {
+          setField(col)
+        }
+      })
     }
   
     // 鍙橀噺澹版槑
@@ -924,7 +926,7 @@
     // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
     _sql += `
         /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
-        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @BillCode='', @ModularDetailCode=''
+        select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
         `
   
     // 琛ㄥ崟鍙橀噺璧嬪��
@@ -943,7 +945,7 @@
     }
 
     _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
-    _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
+    _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') || ''}'`)
@@ -1882,6 +1884,10 @@
     } else if (btn.execSuccess !== 'never') {
       MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn, id, this.state.selines)
     }
+
+    if (window.GLOB.breakpoint) {
+      MKEmitter.emit('refreshDebugTable')
+    }
     
     btn.syncComponentId && MKEmitter.emit('reloadData', btn.syncComponentId)
 
@@ -1941,6 +1947,15 @@
   }
 
   sendWxMessage = (verify, id) => {
+    if (!window.GLOB.nginx) {
+      notification.warning({
+        top: 92,
+        message: 'nginx鏈嶅姟灏氭湭寮�鍚紝涓嶅彲鍙戦�佹ā鏉挎秷鎭��',
+        duration: 5
+      })
+      return
+    }
+    
     let param = {
       func: 's_get_sms_weixin_local',
       upid: id
@@ -2020,6 +2035,7 @@
                 upid: id,
                 send_id: n.client_msg_id || '',
                 status_result: re.errcode === 0 ? 'S' : 'E',
+                errcode: re.errcode,
                 msg_result: re.errmsg
               }
 
@@ -2037,9 +2053,23 @@
                 }
               })
             } else if (re.errcode !== 0 && re.errmsg) {
+              let msgs = [
+                {errcode: -1, errmsg: '绯荤粺绻佸繖锛岃绋嶅�欏啀璇�'},
+                {errcode: 40001, errmsg: 'access_token 鏃犳晥'},
+                {errcode: 40003, errmsg: '涓嶅悎娉曠殑 OpenID'},
+                {errcode: 40014, errmsg: '涓嶅悎娉曠殑 access_token'},
+                {errcode: 40033, errmsg: '涓嶅悎娉曠殑璇锋眰瀛楃'},
+                {errcode: 43004, errmsg: '闇�瑕佹帴鏀惰�呭叧娉�'},
+                {errcode: 43019, errmsg: '闇�瑕佸皢鎺ユ敹鑰呬粠榛戝悕鍗曚腑绉婚櫎'},
+                {errcode: 50005, errmsg: '鐢ㄦ埛鏈叧娉ㄥ叕浼楀彿'}
+              ]
+
+              let msg = msgs.filter(m => m.errcode === re.errcode)[0]
+              msg = msg || re
+
               notification.warning({
                 top: 92,
-                message: re.errmsg,
+                message: msg.errmsg,
                 duration: 5
               })
             }
@@ -2262,6 +2292,10 @@
       let data = this.props.selectedData && this.props.selectedData[0] ? this.props.selectedData[0] : null
       this.setState({check: data && data[btn.field] === btn.openVal})
     }
+
+    if (window.GLOB.breakpoint) {
+      MKEmitter.emit('refreshDebugTable')
+    }
   }
 
   handleModelConfig = (config) => {
@@ -2398,73 +2432,86 @@
 
     btnconfig.fields.forEach(item => {
       if (!item.field) return
-      let _readin = item.readin !== 'false'
-      let _initval = item.initval
+      let _item = {
+        key: item.field,
+        readin: item.readin !== 'false' && item.readin !== 'top',
+        fieldlen: item.fieldlength || 50,
+        writein: item.writein !== 'false',
+        type: item.type
+      }
 
-      if (item.type === 'linkMain' || item.type === 'funcvar') {
+      let _initval = item.initval
+      let _readin = item.readin !== 'false'
+      let _format = item.precision || 'day' // 鏃堕棿鏍煎紡鍖�
+
+      if (item.type === 'funcvar') {
+        _initval = ''
         _readin = false
+        _item.readin = false
+      } else if (item.type === 'linkMain') {
+        _readin = false
+        _item.readin = false
+      } else if (item.type === 'date') {
+        if (_format !== 'day') {
+          _format = 'YYYY-MM-DD HH:mm:ss'
+        } else {
+          _format = 'YYYY-MM-DD'
+        }
+      } else if (item.type === 'datetime') {
+        _item.type = 'date'
+        _format = 'YYYY-MM-DD HH:mm:ss'
       }
 
       let key = item.field.toLowerCase()
 
-      if (item.type === 'linkMain' && BData.hasOwnProperty(key)) {
+      if (_item.type === 'linkMain' && BData.hasOwnProperty(key)) {
         _initval = BData[key]
       } else if (_readin && _data.hasOwnProperty(key)) {
         _initval = _data[key]
-      } else if (item.type === 'date' && _initval) {
-        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD')
-      } else if (item.type === 'datemonth' && _initval) {
+      } else if (_item.type === 'date' && _initval) {
+        _initval = moment().subtract(_initval, 'days').format(_format)
+      } else if (_item.type === 'datemonth' && _initval) {
         _initval = moment().subtract(_initval, 'month').format('YYYY-MM')
-      } else if (item.type === 'datetime' && _initval) {
-        _initval = moment().subtract(_initval, 'days').format('YYYY-MM-DD HH:mm:ss')
       }
 
-      if (_initval === undefined) {
-        _initval = ''
-      }
+      _item.value = _initval === undefined ? '' : _initval
 
-      let _fieldlen = item.fieldlength || 50
-      if (item.type === 'textarea' || item.type === 'fileupload' || item.type === 'multiselect') {
-        _fieldlen = item.fieldlength || 512
-      } else if (item.type === 'number') {
-        _fieldlen = item.decimal ? item.decimal : 0
-      } else if (item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_initval)) { // 鐗规畩瀛楁鏇挎崲
-        _initval = _initval.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
-      }
+      if (_item.type === 'number' || item.declare === 'decimal') {
+        _item.type = 'number'
+        _item.fieldlen = item.decimal || 0
+      } else if (['text', 'textarea', 'linkMain'].includes(_item.type)) {
+        _item.value = _item.value + ''
+        _item.value = _item.value.replace(/\t*|\v*/g, '')       // 鍘婚櫎鍒惰〃绗�
 
-      let _type = item.type
-
-      if (['date', 'datemonth', 'datetime'].includes(_type) && item.declareType === 'nvarchar(50)') {
-        _type = 'text'
-      } else if (item.type === 'rate') {
-        item.rateCount = item.rateCount || 5
-        let allowHalf = item.allowHalf === 'true'
-
-        if (allowHalf) {
-          _initval = parseFloat(_initval)
-          if (_initval % 0.5 !== 0) {
-            _initval = parseInt(_initval)
+        if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
+          _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+        }
+        if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
+          _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
+        }
+        if (_item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
+          if (item.lenControl === 'left') {
+            _item.value = _item.value.substr(0, item.fieldlength)
+          } else {
+            _item.value = _item.value.slice(-item.fieldlength)
           }
-        } else {
-          _initval = parseInt(_initval)
         }
+      } else if (_item.type.indexOf('date') > -1) {
+        if (item.declareType === 'nvarchar(50)') {
+          _item.type = 'text'
+        }
+      } else if (_item.type === 'rate') {
+        let count = item.rateCount || 5
+        _item.value = parseInt(_item.value)
 
-        if (isNaN(_initval) || _initval < 0) {
-          _initval = 0
-        } else if (_initval > item.rateCount) {
-          _initval = item.rateCount
+        if (isNaN(_item.value) || _item.value < 0) {
+          _item.value = 0
+        } else if (_item.value > count) {
+          _item.value = count
         }
       }
 
-      result.push({
-        key: item.field,
-        readonly: item.readonly === 'true',
-        readin: item.readin !== 'false' && item.readin !== 'top',
-        fieldlen: _fieldlen,
-        writein: item.writein !== 'false',
-        type: _type,
-        value: _initval
-      })
+      result.push(_item)
     })
 
     if (btnconfig.setting.display === 'exec') {
diff --git a/src/tabviews/zshare/actionList/tabbutton/index.jsx b/src/tabviews/zshare/actionList/tabbutton/index.jsx
index 8a350a5..6158165 100644
--- a/src/tabviews/zshare/actionList/tabbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { Button, notification } from 'antd'
 
@@ -153,20 +152,17 @@
           primaryId: primaryId
         }
       }
-    } else {
-      let menu = null
+    } else if (btn.MenuID || btn.linkmenu) {
+      let menuId = btn.MenuID || btn.linkmenu.slice(-1)[0]
+      let menu = window.GLOB.mkThdMenus.filter(m => m.MenuID === menuId)[0]
 
-      if (btn.MenuID) {
-        let _menu = this.props.permMenus.filter(m => m.MenuID === btn.MenuID)[0] || ''
+      if (!menu && btn.MenuName && btn.tabType) {
         menu = {
           MenuID: btn.MenuID,
-          MenuName: _menu ? _menu.MenuName : btn.MenuName,
+          MenuName: btn.MenuName,
           MenuNo: btn.MenuNo,
-          type: _menu ? _menu.type : btn.tabType
+          type: btn.tabType
         }
-      } else if (btn.linkmenu && btn.linkmenu.length > 0) {
-        let menu_id = btn.linkmenu.slice(-1)[0]
-        menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
       }
 
       if (!menu) {
@@ -242,14 +238,4 @@
   }
 }
 
-const mapStateToProps = (state) => {
-  return {
-    permMenus: state.permMenus,
-  }
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(TabButton)
\ No newline at end of file
+export default TabButton
\ No newline at end of file
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index 81536d8..daa91b3 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -133,6 +133,9 @@
         readin = false
         item.readin = false
         item.hidden = true
+      } else if (item.type === 'linkMain') {
+        readin = false
+        item.readin = false
       } else if (item.type === 'number') {
         item.decimal = item.decimal || 0
         item.fieldlength = item.decimal
@@ -163,23 +166,16 @@
       if (readin && data.hasOwnProperty(key)) {
         newval = data[key]
       }
-      if (item.type === 'linkMain') {
-        newval = BData[key] || '$empty'
-      } else if (item.type === 'date') { // 鏃堕棿鎼滅储
-        let format = 'YYYY-MM-DD'
+      if (item.type === 'linkMain' && BData.hasOwnProperty(key)) {
+        newval = BData[key]
+      } else if (item.type === 'date') { // 鏃堕棿琛ㄥ崟锛屾彁浜ゅ�间负澶╂垨绉�
         let _format = 'YYYY-MM-DD HH:mm:ss'
         if (item.precision === 'day') {
           _format = 'YYYY-MM-DD'
-        } else if (item.precision === 'hour') {
-          format = 'YYYY-MM-DD HH'
-        } else if (item.precision === 'minute') {
-          format = 'YYYY-MM-DD HH:mm'
-        } else if (item.precision === 'second') {
-          format = 'YYYY-MM-DD HH:mm:ss'
         }
 
         if (newval !== '$empty') {
-          newval = moment(newval, format).format(_format)
+          newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format(_format)
           newval = newval === 'Invalid date' ? '$empty' : newval
         }
         if (newval === '$empty' && item.initval) {
@@ -193,18 +189,6 @@
         if (newval === '$empty' && item.initval) {
           newval = moment().subtract(item.initval, 'month').format('YYYY-MM')
         }
-      // } else if (item.type === 'datetime') {
-      //   if (newval !== '$empty') {
-      //     newval = moment(newval, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD HH:mm:ss')
-      //     newval = newval === 'Invalid date' ? '$empty' : newval
-      //   }
-      //   if (newval === '$empty' && item.initval) {
-      //     if (item.initval === '0') {
-      //       newval = moment().format('YYYY-MM-DD HH:mm:ss')
-      //     } else {
-      //       newval = moment().subtract(item.initval, 'days').format('YYYY-MM-DD') + ' 00:00:00'
-      //     }
-      //   }
       } else if (item.type === 'switch') { // 寮�鍏冲彧鎺ユ敹鍥哄畾鍊�
         if (newval !== '$empty' && (newval === item.closeVal || newval === item.openVal)) {
 
@@ -221,7 +205,11 @@
         item.initval = ''
       }
 
-      if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect', 'cascader'].includes(item.type) && item.resourceType === '1') {
+      if (item.type === 'number') {
+        if (isNaN(item.initval)) {
+          item.initval = 0
+        }
+      } else if (['select', 'link', 'radio', 'checkbox', 'checkcard', 'multiselect', 'cascader'].includes(item.type) && item.resourceType === '1') {
         deForms.push(item)
       } else if (item.type === 'rate') {
         item.rateCount = item.rateCount || 5
@@ -244,9 +232,7 @@
       }
 
       if (item.type === 'text') {
-        if (typeof(item.initval) === 'number') {
-          item.initval = item.initval + ''
-        }
+        item.initval = item.initval + ''
         let _rules = [{
           pattern: /^[^']*$/ig,
           message: '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒'
@@ -274,37 +260,32 @@
           if (item.regular === 'number') {
             _rules.push({
               pattern: /^[0-9.-]*$/,
-              message: formRule.input.numbermsg
+              message: item.regularText || formRule.input.numbermsg
             })
           } else if (item.regular === 'letter') {
             _rules.push({
               pattern: /^[a-zA-Z]*$/,
-              message: formRule.input.lettermsg
+              message: item.regularText || formRule.input.lettermsg
             })
           } else if (item.regular === 'letter_number') {
             _rules.push({
               pattern: /^[a-zA-Z0-9]*$/,
-              message: '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝'
+              message: item.regularText || '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝'
             })
           } else if (item.regular === 'letter&number') {
             _rules.push({
               pattern: /^[a-zA-Z0-9@_.]*$/,
-              message: '璇疯緭鍏ユ暟瀛椼�佸瓧姣嶄互鍙夽_.'
+              message: item.regularText || '璇疯緭鍏ユ暟瀛椼�佸瓧姣嶄互鍙夽_.'
             })
           } else if (item.regular === 'phone') {
             _rules.push({
               pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
-              message: '璇锋纭緭鍏ユ墜鏈哄彿'
+              message: item.regularText || '璇锋纭緭鍏ユ墜鏈哄彿'
             })
           } else if (item.regular === 'email') {
             _rules.push({
               pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
-              message: '璇锋纭緭鍏ラ偖绠卞湴鍧�'
-            })
-          } else if (item.regular === 'funcname') {
-            _rules.push({
-              pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/,
-              message: formRule.input.funcname
+              message: item.regularText || '璇锋纭緭鍏ラ偖绠卞湴鍧�'
             })
           }
         }
@@ -962,7 +943,6 @@
     
           let _item = {
             type: item.type,
-            readonly: item.readonly,
             readin: item.readin,
             writein: item.writein,
             fieldlen: item.fieldlength,
@@ -973,29 +953,29 @@
     
           if (item.type === 'funcvar') {
             _item.value = ''
-          } else if (_item.value && (item.type === 'text' || item.type === 'textarea' || item.type === 'linkMain') && typeof(_item.value) === 'string') {
+          } else if (item.declare === 'decimal') {
+            _item.type = 'number'
+            _item.fieldlen = item.decimal || 0
+          } else if (['text', 'textarea', 'linkMain'].includes(item.type)) {
+            _item.value = _item.value + ''
             _item.value = _item.value.replace(/\t*|\v*/g, '')       // 鍘婚櫎鍒惰〃绗�
     
-            if (item.interception !== 'false') {           // 鍘婚櫎棣栧熬绌烘牸
+            if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
               _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
             }
             if (item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
               _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
             }
+            if (item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
+              if (item.lenControl === 'left') {
+                _item.value = _item.value.substr(0, item.fieldlength)
+              } else {
+                _item.value = _item.value.slice(-item.fieldlength)
+              }
+            }
           } else if (item.type.indexOf('date') > -1) {
             if (item.declareType === 'nvarchar(50)') {
               _item.type = 'text'
-            }
-          } else if (item.declare === 'decimal' && ['select', 'link', 'radio', 'checkcard'].includes(item.type)) {
-            _item.type = 'number'
-            _item.fieldlen = item.decimal || 0
-          }
-
-          if (item.type === 'text' && item.lenControl && item.lenControl !== 'limit') {
-            if (item.lenControl === 'left') {
-              _item.value = _item.value.substr(0, item.fieldlength)
-            } else {
-              _item.value = _item.value.slice(-item.fieldlength)
             }
           }
     
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index b355463..c3147cc 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import md5 from 'md5'
 import { is, fromJS } from 'immutable'
-import { Table, Affix, Typography, Col } from 'antd'
+import { Table, Typography, Col } from 'antd'
 
 import asyncComponent from '@/utils/asyncComponent'
 import MKEmitter from '@/utils/events.js'
@@ -18,6 +18,7 @@
 const TabButton = asyncComponent(() => import('@/tabviews/zshare/actionList/tabbutton'))
 const NewPageButton = asyncComponent(() => import('@/tabviews/zshare/actionList/newpagebutton'))
 const Video = asyncComponent(() => import('@/components/video'))
+const MkPicture = asyncComponent(() => import('@/components/mkPicture'))
 
 const PicRadio = {
   '4:3': '75%', '3:2': '66.67%', '16:9': '56.25%', '2:1': '50%', '3:1': '33.33%', '4:1': '25%',
@@ -660,17 +661,7 @@
       return (
         <div className="picture-col">
           {photos.map((url, i) => (<Col key={i} span={item.span || 24}>
-            <div
-              className={'mk-picture' + (scale ? ' image-scale' : '')}
-              onClick={(e) => {
-                if (!scale) return
-
-                e.stopPropagation()
-
-                MKEmitter.emit('mkImageScale', url, photos)
-              }}
-              style={{...style, backgroundImage: `url('${url}')`}}
-            ></div>
+            <MkPicture style={style} scale={scale} url={url} urls={photos}/>
           </Col>))}
         </div>
       )
@@ -1250,21 +1241,6 @@
       }
     }
 
-    // 琛ㄦ牸澶撮儴鍥哄畾浜庨《閮ㄦ椂锛屽垽鏂窛椤堕儴楂樺害
-    let offset = null
-    if (this.props.tableId === 'mainTable' && setting.columnfixed) {
-      if (!setting.actionfixed) {
-        offset = 48
-      } else {
-        let box = document.getElementById(this.props.MenuID + 'mainaction')
-        if (box) {
-          offset = 48 + box.offsetHeight
-        } else {
-          offset = 105
-        }
-      }
-    }
-
     // 鏁版嵁鏀惰捣鏃讹紝杩囨护宸查�夋暟鎹�
     let _data = this.props.data ? this.props.data : []
 
@@ -1308,22 +1284,6 @@
 
     return (
       <div className={'normal-data-table mingke-table ' + (height ? 'fixed-height' : '')}>
-        {offset && <Affix offsetTop={offset} className="fix-header">
-          <Table
-            size={setting.size || 'middle'}
-            style={style}
-            bordered={setting.bordered !== 'false'}
-            rowSelection={rowSelection}
-            columns={this.state.columns.map(column => {
-              return {
-                align: column.align,
-                dataIndex: column.dataIndex,
-                title: column.title,
-                width: column.width
-              }
-            })}
-          />
-        </Affix>}
         <Table
           components={components}
           size={setting.size || 'middle'}
diff --git a/src/tabviews/zshare/normalTable/index.scss b/src/tabviews/zshare/normalTable/index.scss
index 0011eac..75c4770 100644
--- a/src/tabviews/zshare/normalTable/index.scss
+++ b/src/tabviews/zshare/normalTable/index.scss
@@ -174,15 +174,6 @@
           >.ant-col {
             padding: 5px;
           }
-          .mk-picture {
-            background-color: #f5f5f5;
-            background-position: center center;
-            background-size: cover;
-            background-repeat: no-repeat;
-          }
-          .image-scale {
-            cursor: zoom-in;
-          }
         }
         .action-col {
           .ant-btn > .anticon + span {
diff --git a/src/tabviews/zshare/settingcomponent/index.jsx b/src/tabviews/zshare/settingcomponent/index.jsx
index c877b05..ce4540b 100644
--- a/src/tabviews/zshare/settingcomponent/index.jsx
+++ b/src/tabviews/zshare/settingcomponent/index.jsx
@@ -17,7 +17,6 @@
     dict: PropTypes.object,           // 瀛楀吀琛�
     config: PropTypes.object,         // 椤甸潰閰嶇疆淇℃伅
     shortcuts: PropTypes.any,         // 鑷畾涔夎缃�
-    permAction: PropTypes.object,     // 鎸夐挳鏉冮檺
   }
 
   state = {
@@ -183,7 +182,7 @@
   }
 
   getPageConfig = () => {
-    const { shortcuts, permAction } = this.props
+    const { shortcuts } = this.props
     let config = fromJS(this.props.config).toJS()
     let userConfig = {}
     let components = []
@@ -262,7 +261,7 @@
           let _comp = {title: res.tab.label, uuid: res.tab.uuid, action: []}
 
           subconfig.action.forEach(item => {
-            if (!permAction[item.uuid]) return
+            if (!window.GLOB.mkActions[item.uuid]) return
 
             item.$expanded = false
             if (item.OpenType === 'funcbutton' && item.funcType === 'print') {
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index ec2efcb..3717e24 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
@@ -1805,12 +1804,4 @@
   }
 }
 
-const mapStateToProps = () => {
-  return {}
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(ComTableConfig)
+export default ComTableConfig
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 9f35ed0..f21d14e 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import {connect} from 'react-redux'
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
@@ -888,12 +887,4 @@
   }
 }
 
-const mapStateToProps = () => {
-  return {}
-}
-
-const mapDispatchToProps = () => {
-  return {}
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(ComModalConfig)
\ No newline at end of file
+export default ComModalConfig
\ No newline at end of file
diff --git a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
index 19ab1ec..27bd86b 100644
--- a/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -561,6 +561,11 @@
             { pattern: _patten, message: formRule.func.innerMessage },
             { max: formRule.func.max, message: formRule.func.maxMessage }
           )
+        } else if (item.key === 'sql' || item.key === 'sheet') {
+          rules.push(
+            { pattern: /^[a-zA-Z_]+$/, message: '琛ㄥ悕鍙彲浣跨敤瀛楁瘝浠ュ強_' },
+            { max: formRule.func.max, message: formRule.func.maxMessage }
+          )
         } else if (item.key === 'outerFunc' || item.key === 'callbackFunc') {
           rules.push(
             { pattern: formRule.func.pattern, message: formRule.func.message },
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index 5d026be..1361104 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -277,6 +277,17 @@
   }
 
   componentDidMount () {
+    this.getsysScript()
+  }
+
+  getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+    
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -290,18 +301,21 @@
     
     _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
-
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
+        let _scripts = res.data.map(item => {
+          return {
+            name: item.funcname,
+            value: window.decodeURIComponent(window.atob(item.longparam))
+          }
+        })
+
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
         this.setState({
-          systemScripts: res.data.map(item => {
-            return {
-              name: item.funcname,
-              value: window.decodeURIComponent(window.atob(item.longparam))
-            }
-          })
+          systemScripts: _scripts
         })
       } else {
         notification.warning({
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 62d925c..0431f00 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -294,6 +294,17 @@
   }
 
   componentDidMount () {
+    this.getsysScript()
+  }
+
+  getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+    
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -307,18 +318,21 @@
     
     _sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     _sParam.secretkey = Utils.encrypt(_sParam.LText, _sParam.timestamp)
-
     _sParam.open_key = Utils.encryptOpenKey(_sParam.secretkey, _sParam.timestamp) // 浜戠鏁版嵁楠岃瘉
     
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
+        let _scripts = res.data.map(item => {
+          return {
+            name: item.funcname,
+            value: window.decodeURIComponent(window.atob(item.longparam))
+          }
+        })
+
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
         this.setState({
-          systemScripts: res.data.map(item => {
-            return {
-              name: item.funcname,
-              value: window.decodeURIComponent(window.atob(item.longparam))
-            }
-          })
+          systemScripts: _scripts
         })
       } else {
         notification.warning({
@@ -900,6 +914,11 @@
   sqlverify = (_resolve, _reject, scripts) => {
     const { searches, verify } = this.state
 
+    if (verify.dataType !== 'custom') {
+      _resolve()
+      return
+    }
+
     let timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
     let sql = SettingUtils.getDebugSql(verify, scripts, searches, Utils, timestamp)
     let param = {
diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx
index d2c3f5d..72b3c79 100644
--- a/src/templates/sharecomponent/settingcomponent/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/index.jsx
@@ -71,7 +71,6 @@
         loading: false
       })
       res.actionfixed = res.actionfixed === 'true'
-      res.columnfixed = res.columnfixed === 'true'
 
       this.props.updatesetting({...config, setting: res})
 
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
index e80b861..5ce74b1 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/datasource/index.jsx
@@ -27,8 +27,6 @@
 
   state = {
     interType: 'system',
-    procMode: 'script',
-    requestMode: 'system',
     sysInterface: 'false',
     controlField: '',
     tableType: '',
@@ -66,8 +64,6 @@
 
     this.setState({
       interType: setting.interType || 'system',
-      procMode: setting.procMode || 'script',
-      requestMode: setting.requestMode || 'system',
       controlField: setting.controlField || '',
       sysInterface: setting.sysInterface || 'false',
       tableType: setting.tableType,
@@ -172,14 +168,6 @@
       this.setState({
         interType: value
       })
-    } else if (key === 'procMode') {
-      this.setState({
-        procMode: value
-      })
-    } else if (key === 'requestMode') {
-      this.setState({
-        requestMode: value
-      })
     } else if (key === 'sysInterface') {
       this.setState({
         sysInterface: value
@@ -204,7 +192,7 @@
   render() {
     const { setting, dict, menu, config, columns } = this.props
     const { getFieldDecorator } = this.props.form
-    const { interType, funcRules, funcTooltip, procMode, requestMode, tableType, controlField, sysInterface } = this.state
+    const { interType, funcRules, funcTooltip, tableType, controlField, sysInterface } = this.state
 
     const formItemLayout = {
       labelCol: {
@@ -232,6 +220,10 @@
                   {
                     max: 50,
                     message: '琛ㄥ悕鏈�闀夸负50涓瓧绗�!'
+                  },
+                  {
+                    pattern: /^[a-zA-Z_]+$/,
+                    message: '琛ㄥ悕鍙彲浣跨敤瀛楁瘝浠ュ強_'
                   }
                 ]
               })(<Input placeholder={''} autoComplete="off" />)}
@@ -252,7 +244,6 @@
                 <Radio value="system">绯荤粺</Radio>
                 <Radio value="inner">鍐呴儴</Radio>
                 <Radio value="outer">澶栭儴</Radio>
-                <Radio value="custom">鑷畾涔�</Radio>
               </Radio.Group>)}
             </Form.Item>
           </Col>
@@ -286,47 +277,7 @@
               </Radio.Group>)}
             </Form.Item>
           </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="鍙傛暟澶勭悊">
-              {getFieldDecorator('procMode', {
-                initialValue: procMode,
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.select'] + '鍙傛暟澶勭悊鏂瑰紡!'
-                  },
-                ]
-              })(
-              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'procMode')}}>
-                <Radio value="script">鍓嶇疆鑴氭湰</Radio>
-                <Radio value="inner">鍓嶇疆鍑芥暟</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' && procMode === 'inner' ? <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title={funcTooltip}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鍓嶇疆鍑芥暟
-              </Tooltip>
-            }>
-              {getFieldDecorator('prevFunc', {
-                initialValue: setting.prevFunc || '',
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '鍓嶇疆鍑芥暟!'
-                  },
-                  {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  },
-                  ...funcRules
-                ]
-              })(<Input placeholder={''} autoComplete="off" />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' || interType === 'custom' ? <Col className="mk-through-line3" span={24}>
+          {interType === 'outer' ? <Col className="mk-through-line3" span={24}>
             <Form.Item label="鎺ュ彛鍦板潃">
               {getFieldDecorator('interface', {
                 initialValue: setting.interface || (interType === 'outer' && sysInterface === 'true' ? window.GLOB.mainSystemApi : ''),
@@ -339,7 +290,7 @@
               })(<TextArea rows={2} readOnly={interType === 'outer' && sysInterface === 'true'}/>)}
             </Form.Item>
           </Col> : null}
-          {(interType === 'outer' && sysInterface !== 'true') || interType === 'custom' ? <Col className="mk-through-line3" span={24}>
+          {interType === 'outer' && sysInterface !== 'true' ? <Col className="mk-through-line3" span={24}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="姝e紡绯荤粺鎵�浣跨敤鐨勭殑鎺ュ彛鍦板潃銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -351,41 +302,7 @@
               })(<TextArea rows={2} />)}
             </Form.Item>
           </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="璇锋眰鏂瑰紡">
-              {getFieldDecorator('method', {
-                initialValue: setting.method || 'post',
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.select'] + '璇锋眰鏂瑰紡!'
-                  },
-                ]
-              })(
-              <Radio.Group>
-                <Radio value="get">GET</Radio>
-                <Radio value="post">POST</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="鏁版嵁璇锋眰">
-              {getFieldDecorator('requestMode', {
-                initialValue: requestMode,
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.select'] + '鏁版嵁璇锋眰鏂瑰紡!'
-                  },
-                ]
-              })(
-              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'requestMode')}}>
-                <Radio value="system">绯荤粺鍑芥暟</Radio>
-                <Radio value="inner">鍐呴儴鍑芥暟</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'inner' || (interType === 'custom' && requestMode === 'inner') ? <Col span={8}>
+          {interType === 'inner' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="topLeft" title={funcTooltip}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -424,7 +341,7 @@
               })(<Input placeholder={''} autoComplete="off" />)}
             </Form.Item>
           </Col> : null}
-          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={24} className="mk-through-line3">
+          {interType === 'system' ? <Col span={24} className="mk-through-line3">
             <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } label={
               <Tooltip placement="topLeft" title={`浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愩�傛敞锛氭暟鎹潈闄愭浛鎹㈢ $@ -> /* 鎴� ''銆� @$ -> */ 鎴� ''锛涙煡璇㈡浛鎹㈢ $select@ -> /* 鎴� ''銆� @select$ -> */ 鎴� ''锛涚粺璁℃浛鎹㈢ $sum@ -> /* 鎴� ''銆� @sum$ -> */ 鎴� ''銆俙}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -436,7 +353,7 @@
               })(<CodeMirror />)}
             </Form.Item>
           </Col> : null}
-          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={8}>
+          {interType === 'system' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="topLeft" title={'鏌ヨ鏃讹紝鎼滅储鏉′欢浠here鏉′欢鎷兼帴杩涘叆sql锛岀粺璁℃椂锛屽皢鏁版嵁婧愪腑浠モ�淍+鎼滅储瀛楁+@鈥濈殑鍐呭锛屼互鎼滅储鏉′欢涓殑鍊艰繘琛屾浛鎹㈠悗锛屾彁浜ゆ煡璇紝娉細鏌ヨ绫诲瀷浠呭湪浣跨敤绯荤粺鍑芥暟鏃舵湁鏁堛��'}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -452,7 +369,7 @@
               </Radio.Group>)}
             </Form.Item>
           </Col> : null}
-          {interType === 'system' || (interType === 'custom' && requestMode === 'system') ? <Col span={8}>
+          {interType === 'system' ? <Col span={8}>
             <Form.Item label="榛樿sql">
               {getFieldDecorator('default', {
                 initialValue: setting.default || 'true'
@@ -496,77 +413,6 @@
               })(<Input placeholder={'ID asc, UID desc'} autoComplete="off" />)}
             </Form.Item>
           </Col>
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="鍥炶皟鏂瑰紡">
-              {getFieldDecorator('callbackType', {
-                initialValue: setting.callbackType || 'script'
-              })(
-              <Radio.Group onChange={(e) => {this.onRadioChange(e, 'callbackType')}}>
-                <Radio value="default">榛樿鑴氭湰</Radio>
-                <Radio value="script">鑷畾涔夎剼鏈�</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="鍥炶皟琛ㄥ悕">
-              {getFieldDecorator('cbTable', {
-                initialValue: setting.cbTable || '',
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '鍥炶皟琛ㄥ悕!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder={''} autoComplete="off" />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title={'鍚屾鎵ц锛氬閮ㄦ帴鍙h皟鐢ㄦ垚鍔熷悗鍐嶈姹傛暟鎹紱寮傛鎵ц锛氬閮ㄦ帴鍙h皟鐢ㄤ笌璇锋眰鏁版嵁鍚屾椂杩涜銆�'}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鎵ц鏂瑰紡
-              </Tooltip>
-            }>
-              {getFieldDecorator('execType', {
-                initialValue: setting.execType || 'sync'
-              })(
-              <Radio.Group>
-                <Radio value="sync">鍚屾</Radio>
-                <Radio value="async">寮傛</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title={'濡傛灉鑷畾涔夋帴鍙d笉鏀寔璺ㄥ煙璇锋眰锛屼細閫氳繃褰撳墠绯荤粺杞彂銆�'}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                璺ㄥ煙璇锋眰
-              </Tooltip>
-            }>
-              {getFieldDecorator('cross', {
-                initialValue: setting.cross || 'true'
-              })(
-              <Radio.Group>
-                <Radio value="true">鏀寔</Radio>
-                <Radio value="false">涓嶆敮鎸�</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'custom' ? <Col span={8}>
-            <Form.Item label="鎵ц娆℃暟">
-              {getFieldDecorator('execTime', {
-                initialValue: setting.execTime || 'once'
-              })(
-              <Radio.Group>
-                <Radio value="always">濮嬬粓</Radio>
-                <Radio value="once">涓�娆�</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> : null}
           <Col span={8}>
             <Form.Item label="鏄惁鍒嗛〉">
               {getFieldDecorator('laypage', {
@@ -600,7 +446,7 @@
               </Radio.Group>)}
             </Form.Item>
           </Col> : null}
-          {config.Template === 'CommonTable' ? <Col span={8}>
+          {/* {config.Template === 'CommonTable' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="topLeft" title={'鍚湁鍚堝苟鍒楁垨琛ㄦ牸鍑虹幇妯悜婊氬姩鏃朵細鏄剧ず寮傚父锛岃鎱庣敤锛�'}>
                 <QuestionCircleOutlined className="mk-form-tip" />
@@ -615,7 +461,7 @@
                 <Radio value="false">{dict['model.false']}</Radio>
               </Radio.Group>)}
             </Form.Item>
-          </Col> : null}
+          </Col> : null} */}
           <Col span={8}>
             <Form.Item label="杈规">
               {getFieldDecorator('bordered', {
@@ -688,22 +534,6 @@
               </Radio.Group>)}
             </Form.Item>
           </Col>
-          {/* <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鍦ㄦ悳绱㈡潯浠跺瓨鍦ㄦ椂锛屾槸鍚︽樉绀烘悳绱㈠拰閲嶇疆鎸夐挳銆�">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                鎼滅储鎸夐挳
-              </Tooltip>
-            }>
-              {getFieldDecorator('show', {
-                initialValue: setting.show || 'true'
-              })(
-              <Radio.Group>
-                <Radio value="true">鏄剧ず</Radio>
-                <Radio value="false">闅愯棌</Radio>
-              </Radio.Group>)}
-            </Form.Item>
-          </Col> */}
           {tableType !== '' ? <Col span={8}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="褰撴寜閽墽琛屽畬鎴愬苟杩斿洖涓婚敭鍊兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇銆傛敞锛氬湪鍚敤鏃犱汉鍊煎畧鍔熻兘鏃舵棤鏁堛��">
@@ -733,18 +563,6 @@
               })(<InputNumber min={1} max={500} precision={0} />)}
             </Form.Item>
           </Col>
-          {/* <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��">
-                <QuestionCircleOutlined className="mk-form-tip" />
-                楂樼骇鎼滅储
-              </Tooltip>
-            }>
-              {getFieldDecorator('advanceWidth', {
-                initialValue: setting.advanceWidth || 1000
-              })(<InputNumber min={10} max={3000} precision={0}/>)}
-            </Form.Item>
-          </Col> */}
           <Col span={8}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="鍙屽嚮琛ㄦ牸涓锛岃Е鍙戠殑鎸夐挳銆�">
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
index deae870..3ae2a2c 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.jsx
@@ -17,7 +17,6 @@
 const { Paragraph } = Typography
 const CodeMirror = asyncComponent(() => import('@/templates/zshare/codemirror'))
 const CustomScript = asyncComponent(() => import('@/templates/zshare/customscript'))
-const SimpleScript = asyncComponent(() => import('./simplescript'))
 
 class SettingForm extends Component {
   static propTpyes = {
@@ -48,8 +47,6 @@
 
     let _setting = fromJS(config.setting).toJS()
     let _scripts = _setting.scripts || []
-    let _preScripts = _setting.preScripts || []
-    let _cbScripts = _setting.cbScripts || []
 
     _setting.default = _setting.default || 'true'            // 榛樿sql
     _setting.sysInterface = _setting.sysInterface || 'false' // 鏄惁涓虹郴缁熸帴鍙�
@@ -90,9 +87,6 @@
     _search = _search ? 'where ' + _search : ''
 
     let status = fromJS(_setting).toJS()
-    status.requestMode = status.requestMode || 'system'
-    status.procMode = status.procMode || 'script'
-    status.callbackType = status.callbackType || 'script'
     let regoptions = this.getRegOptions(search)
 
     if (config.urlFields && config.urlFields.length > 0) {
@@ -111,12 +105,6 @@
         _scripts.forEach(item => {
           item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
         })
-        _preScripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
-        _cbScripts.forEach(item => {
-          item.sql = item.sql.replace(reg, `$ex@${m.func_code}@ex$`)
-        })
         if (_setting.dataresource) {
           _setting.dataresource = _setting.dataresource.replace(reg, `$ex@${m.func_code}@ex$`)
         }
@@ -130,8 +118,6 @@
       regoptions: regoptions, // 鎼滅储鏉′欢锛屾鍒欐浛鎹�
       columns: columns,
       scripts: _scripts,
-      preScripts: _preScripts,
-      cbScripts: _cbScripts,
       status
     })
   }
@@ -241,18 +227,9 @@
   }
 
   handleConfirm = (trigger) => {
-    const { activeKey, setting, scripts, preScripts, cbScripts } = this.state
+    const { activeKey, setting, scripts } = this.state
 
-    let _loading = false
     if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    }
-
-    if (_loading) {
       notification.warning({
         top: 92,
         message: '瀛樺湪鏈繚瀛樿剼鏈紝璇风偣鍑荤‘瀹氫繚瀛橈紝鎴栫偣鍑诲彇娑堟斁寮冧慨鏀癸紒',
@@ -274,7 +251,7 @@
           }, () => {
             this.sqlverify(() => {
               this.setState({loading: false})
-              resolve({...res, scripts, preScripts, cbScripts})
+              resolve({...res, scripts})
             }, () => {
               this.setState({loading: false})
               reject()
@@ -289,7 +266,7 @@
       return new Promise((resolve, reject) => {
         this.sqlverify(() => {
           this.setState({loading: false})
-          resolve({...setting, scripts, preScripts, cbScripts})
+          resolve({...setting, scripts})
         }, () => {
           this.setState({loading: false})
           reject()
@@ -298,7 +275,7 @@
     } else {
       this.setState({loading: false})
       return new Promise((resolve) => {
-        resolve({...setting, scripts, preScripts, cbScripts})
+        resolve({...setting, scripts})
       })
     }
   }
@@ -306,7 +283,7 @@
   sqlverify = (_resolve, _reject, type, uscripts) => {
     const { setting, scripts, arr_field, regoptions, search } = this.state
 
-    if (setting.interType !== 'system' && setting.requestMode !== 'system') { // 涓嶄娇鐢ㄧ郴缁熸帴鍙f椂锛屼笉闇�瑕乻ql楠岃瘉
+    if (setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熸帴鍙f椂锛屼笉闇�瑕乻ql楠岃瘉
       _resolve()
       return
     }
@@ -382,18 +359,9 @@
 
   // 鏍囩鍒囨崲
   changeTab = (val) => {
-    const { activeKey, search, arr_field, setting } = this.state
+    const { activeKey, search, arr_field } = this.state
 
-    let _loading = false
     if (this.scriptsForm && this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.preScriptsForm && this.preScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.preScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    } else if (this.cbScriptsForm && this.cbScriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.cbScriptsForm.props.form.getFieldValue('sql'))) {
-      _loading = true
-    }
-
-    if (_loading) {
       notification.warning({
         top: 92,
         message: '瀛樺湪鏈繚瀛樿剼鏈紝璇风偣鍑荤‘瀹氫繚瀛橈紝鎴栫偣鍑诲彇娑堟斁寮冧慨鏀癸紒',
@@ -402,43 +370,9 @@
       return
     }
 
-    if (activeKey !== 'setting') {
-      if (setting.interType !== 'system' && setting.requestMode !== 'system' && val === 'scripts') {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤绯荤粺鎺ュ彛鏃讹紝鎵嶅彲浠ヨ缃嚜瀹氫箟鑴氭湰锛�',
-          duration: 5
-        })
-        return
-      } else if (setting.interType !== 'custom' && (val === 'prescripts' || val === 'cbscripts')) {
-        notification.warning({
-          top: 92,
-          message: '浣跨敤鑷畾涔夋帴鍙f椂锛屾墠鍙互璁剧疆鍓嶇疆鎴栧洖璋冭剼鏈紒',
-          duration: 5
-        })
-        return
-      }
-    }
-
     if (activeKey === 'setting') {
       let _defaultSql = ''
       this.settingForm.handleConfirm().then(res => {
-        if (res.interType !== 'system' && res.requestMode !== 'system' && val === 'scripts') {
-          notification.warning({
-            top: 92,
-            message: '浣跨敤绯荤粺鎺ュ彛鏃讹紝鎵嶅彲浠ヨ缃嚜瀹氫箟鑴氭湰锛�',
-            duration: 5
-          })
-          return
-        } else if (res.interType !== 'custom' && (val === 'prescripts' || val === 'cbscripts')) {
-          notification.warning({
-            top: 92,
-            message: '浣跨敤鑷畾涔夋帴鍙f椂锛屾墠鍙互璁剧疆鍓嶇疆鎴栧洖璋冭剼鏈紒',
-            duration: 5
-          })
-          return
-        }
-
         if (res.dataresource) {
           let _dataresource = res.dataresource
 
@@ -534,16 +468,6 @@
   scriptsUpdate = (scripts) => {
     this.setState({scripts})
   }
-  
-  // 鍓嶇疆鑴氭湰鏇存柊
-  preScriptsUpdate = (preScripts) => {
-    this.setState({preScripts})
-  }
-  
-  // 鍚庣疆鑴氭湰鏇存柊
-  cbScriptsUpdate = (cbScripts) => {
-    this.setState({cbScripts})
-  }
 
   handleDelete = (item) => {
     const { script, scripts } = this.state
@@ -573,7 +497,7 @@
 
   render() {
     const { config, menu, dict } = this.props
-    const { loading, activeKey, setting, defaultSql, columns, scripts, preScripts, cbScripts, status, regoptions, visible, script, scriptValue } = this.state
+    const { loading, activeKey, setting, defaultSql, columns, scripts, status, visible, script, scriptValue } = this.state
 
     return (
       <div className="model-table-setting-form-box">
@@ -596,7 +520,7 @@
               鑷畾涔夎剼鏈�
               {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
             </span>
-          } disabled={!(status.interType === 'system' || (status.interType === 'custom' && status.requestMode === 'system'))} key="scripts" id="mk-setting-scripts">
+          } disabled={status.interType !== 'system'} key="scripts" id="mk-setting-scripts">
             {scripts.length ? <BorderOutlined className="full-scripts" onClick={() => {
               if (this.scriptsForm && (this.scriptsForm.state.editItem || (this.scriptsForm.props.form.getFieldValue('sql') && !/^\s+$/.test(this.scriptsForm.props.form.getFieldValue('sql'))))) {
                 notification.warning({
@@ -618,37 +542,6 @@
               scriptsChange={this.scriptsChange}
               scriptsUpdate={this.scriptsUpdate}
               wrappedComponentRef={(inst) => this.scriptsForm = inst}
-            />
-          </TabPane>
-          <TabPane tab={
-            <span>
-              鍓嶇疆鑴氭湰
-              {preScripts.length ? <span className="count-tip">{preScripts.length}</span> : null}
-            </span>
-          } disabled={status.interType !== 'custom' || status.procMode !== 'script'} key="prescripts">
-            <SimpleScript
-              dict={dict}
-              setting={setting}
-              scripts={preScripts}
-              regoptions={regoptions}
-              urlFields={config.urlFields}
-              searches={this.props.search}
-              scriptsUpdate={this.preScriptsUpdate}
-              wrappedComponentRef={(inst) => this.preScriptsForm = inst}
-            />
-          </TabPane>
-          <TabPane tab={
-            <span>
-              鍥炶皟鑴氭湰
-              {cbScripts.length ? <span className="count-tip">{cbScripts.length}</span> : null}
-            </span>
-          } disabled={status.interType !== 'custom' || status.callbackType !== 'script'} key="cbscripts">
-            <SimpleScript
-              dict={dict}
-              setting={setting}
-              scripts={cbScripts}
-              scriptsUpdate={this.cbScriptsUpdate}
-              wrappedComponentRef={(inst) => this.cbScriptsForm = inst}
             />
           </TabPane>
         </Tabs>
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/index.scss b/src/templates/sharecomponent/settingcomponent/settingform/index.scss
index 8790751..57831fe 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/index.scss
+++ b/src/templates/sharecomponent/settingcomponent/settingform/index.scss
@@ -27,6 +27,13 @@
       }
     }
   }
+  .mk-color-move {
+    height: 40px;
+    .color-sketch-block {
+      position: relative;
+      top: 7px;
+    }
+  }
   .operation-btn {
     display: inline-block;
     font-size: 16px;
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
index 8b00a43..8cdffeb 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/simplescript/index.jsx
@@ -152,6 +152,13 @@
   }
 
   getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
+    
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -170,13 +177,14 @@
     Api.getSystemConfig(_sParam).then(res => {
       if (res.status) {
         let _scripts = res.data.map(item => {
-          let _item = {
+          return {
             name: item.funcname,
             value: window.decodeURIComponent(window.atob(item.longparam))
           }
-          return _item
         })
 
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
         this.setState({
           systemScripts: _scripts
         })
diff --git a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
index 2f6b872..b165395 100644
--- a/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
+++ b/src/templates/sharecomponent/settingcomponent/settingform/utils.jsx
@@ -157,7 +157,7 @@
         }
         scripts && scripts.forEach(script => {
           if (reg.test(script.sql)) {
-            errors.push(`鑷畾涔夎剼鏈�(${script.$index})瀛樺湪鏈浛鎹㈠��${item}`)
+            errors.push(`鑷畾涔夎剼鏈�(${script.$index || ''})瀛樺湪鏈浛鎹㈠��${item}`)
           }
         })
       })
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index 5a084df..77b174e 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -68,6 +68,8 @@
 
     Api.getSystemCacheConfig(param).then(res => {
       if (res.status) {
+        let tbNames = res.data.map(item => item.TbName).join(',')
+        sessionStorage.setItem('mk_tb_names', ',' + tbNames.toLowerCase() + ',')
         this.setState({
           tables: res.data
         })
@@ -82,7 +84,7 @@
   }
 
   gettableFields = () => {
-    let deffers = this.state.selectedTables.map(item => {
+    let deffers = this.state.selectedTables.map((item, i) => {
       return new Promise(resolve => {
         let param = {func: 'sPC_Get_FieldName', TBName: item.TbName}
         if (options.cloudServiceApi) { // 涓斿瓨鍦ㄤ簯绔湴鍧�
@@ -91,10 +93,12 @@
           param.LoginUID = sessionStorage.getItem('CloudLoginUID') || ''
         }
 
-        Api.getSystemCacheConfig(param).then(res => {
-          res.TBName = item.TbName
-          resolve(res)
-        })
+        setTimeout(() => {
+          Api.getSystemCacheConfig(param).then(res => {
+            res.TBName = item.TbName
+            resolve(res)
+          })
+        }, (i + 1) * 100)
       })
     })
     Promise.all(deffers).then(response => {
diff --git a/src/templates/zshare/customscript/index.jsx b/src/templates/zshare/customscript/index.jsx
index ecaa177..c5d3eb8 100644
--- a/src/templates/zshare/customscript/index.jsx
+++ b/src/templates/zshare/customscript/index.jsx
@@ -122,6 +122,12 @@
   }
 
   getsysScript = () => {
+    if (sessionStorage.getItem('mk_sys_scripts')) {
+      this.setState({
+        systemScripts: JSON.parse(sessionStorage.getItem('mk_sys_scripts'))
+      })
+      return
+    }
     let _scriptSql = `Select distinct func+Remark as funcname,longparam, s.Sort from聽 s_custom_script s inner join (select OpenID from sapp where ID=@Appkey@) p on s.openid = case when s.appkey='' then s.openid else p.OpenID end order by s.Sort`
 
     _scriptSql = Utils.formatOptions(_scriptSql)
@@ -147,6 +153,8 @@
           return _item
         })
 
+        sessionStorage.setItem('mk_sys_scripts', JSON.stringify(_scripts))
+
         this.setState({
           systemScripts: _scripts
         })
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index 0319a12..91e86e8 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -364,7 +364,47 @@
     let data = fromJS(this.state.data).toJS()
 
     this.pasteFormRef.handleConfirm().then(res => {
-      if (res.key !== type) {
+      if (res.copyType === 'columns' && type === 'datasourcefield') {
+        res.type = 'array'
+        res.data = []
+        res.columns.forEach(col => {
+          if (!col.field) return
+          if (col.type === 'number') {
+            let datatype = 'Int'
+            if (col.decimal) {
+              datatype = `Decimal(18,${col.decimal})`
+            }
+
+            res.data.push({
+              $index: res.data.length + 1,
+              datatype: datatype,
+              field: col.field,
+              decimal: col.decimal,
+              label: col.label,
+              type: 'number',
+              uuid: Utils.getuuid()
+            })
+          } else {
+            let datatype = 'Nvarchar(50)'
+            let fieldlength = 50
+            if (col.fieldlength && [10, 20, 50, 100, 256, 512, 1024, 2048].includes(col.fieldlength)) {
+              fieldlength = col.fieldlength
+              datatype = `Nvarchar(${fieldlength})`
+            }
+
+            res.data.push({
+              $index: res.data.length + 1,
+              datatype: datatype,
+              field: col.field,
+              fieldlength: fieldlength,
+              label: col.label,
+              type: 'text',
+              uuid: Utils.getuuid()
+            })
+          }
+
+        })
+      } else if (res.key !== type) {
         message.warning('閰嶇疆淇℃伅鏍煎紡閿欒锛�')
         return
       }
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 0195364..eeb7fbc 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -3571,6 +3571,24 @@
       required: false
     },
     {
+      type: 'radio',
+      key: 'lenControl',
+      label: '闀垮害鎺у埗',
+      initVal: card.lenControl || 'limit',
+      tooltip: '鍦ㄨ缃瓧娈甸暱搴﹀悗锛屽闀垮害鐨勬帶鍒舵柟寮忋��',
+      required: false,
+      options: [{
+        value: 'limit',
+        text: '闄愬埗杈撳叆'
+      }, {
+        value: 'left',
+        text: '宸︽埅'
+      }, {
+        value: 'right',
+        text: '鍙虫埅'
+      }]
+    },
+    {
       type: 'number',
       key: 'span',
       min: 1,
@@ -3602,24 +3620,6 @@
       }, {
         value: 6,
         text: 6
-      }]
-    },
-    {
-      type: 'radio',
-      key: 'lenControl',
-      label: '闀垮害鎺у埗',
-      initVal: card.lenControl || 'limit',
-      tooltip: '鍦ㄨ缃瓧娈甸暱搴﹀悗锛屽闀垮害鐨勬帶鍒舵柟寮忋��',
-      required: false,
-      options: [{
-        value: 'limit',
-        text: '闄愬埗杈撳叆'
-      }, {
-        value: 'left',
-        text: '宸︽埅'
-      }, {
-        value: 'right',
-        text: '鍙虫埅'
       }]
     },
     {
@@ -3687,6 +3687,15 @@
     },
     {
       type: 'text',
+      key: 'regularText',
+      label: '姝e垯鎻愮ず',
+      initVal: card.regularText || '',
+      tooltip: '姝e垯楠岃瘉鏃剁殑鎻愮ず淇℃伅銆�',
+      required: false,
+      readonly: false
+    },
+    {
+      type: 'text',
       key: 'tooltip',
       label: '鎮诞鎻愮ず',
       tooltip: '榧犳爣鎮诞浜庢彁绀烘枃瀛椾笂鏂规椂锛屾樉绀烘彁绀轰俊鎭��',
@@ -3722,7 +3731,7 @@
     {
       type: 'text',
       key: 'placeholder',
-      label: '鎻愮ず淇℃伅',
+      label: '杈撳叆鎻愮ず',
       tooltip: '瀛楁棰勬湡鍊肩殑鎻愮ず淇℃伅銆�',
       initVal: card.placeholder || '',
       required: false
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 6a9fba9..9be8093 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -41,7 +41,7 @@
   formula: ['label', 'type', 'marginTop', 'marginBottom', 'splitline', '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'],
-  linkMain: ['readonly', 'required', 'hidden', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'marginTop', 'marginBottom']
+  linkMain: ['readonly', 'required', 'hidden','declare', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'marginTop', 'marginBottom']
 }
 
 class MainSearch extends Component {
@@ -140,6 +140,9 @@
       if (this.record.enter === 'tab' || this.record.enter === 'sub') {
         shows.push('tabField')
       }
+      if (this.record.regular !== '') {
+        shows.push('regularText')
+      }
     } else if (type === 'number') {
       reTypes.initval = 'number'
       reRequired.initval = true
@@ -149,6 +152,12 @@
       if (sessionStorage.getItem('appType') === 'mob') { // 绉诲姩绔彸渚ф墿灞曚俊鎭�
         shows.push('placeholder')
       }
+    } else if (type === 'linkMain') {
+      if (this.record.declare === 'nvarchar') {
+        shows.push('fieldlength')
+      } else if (this.record.declare === 'decimal') {
+        shows.push('decimal')
+      }
     } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(type)) {
       if (this.record.resourceType === '0') {        // 鑷畾涔夎祫婧�
         shows.push('options')
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index 49dbd06..19fdbf9 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -29,7 +29,7 @@
     const { verify } = this.props
     let wxTemps = sessionStorage.getItem('wxTemplates')
 
-    if (window.GLOB.WXAppID && !wxTemps) {
+    if (window.GLOB.WXAppID && window.GLOB.nginx && !wxTemps) {
       Api.wxAccessToken().then(res => {
         let wxtoken = res.oa_access_token || ''
         // let minitoken = res.mini_access_token || ''
diff --git a/src/templates/zshare/verifycard/customscript/index.jsx b/src/templates/zshare/verifycard/customscript/index.jsx
index 7b42a66..e5542bd 100644
--- a/src/templates/zshare/verifycard/customscript/index.jsx
+++ b/src/templates/zshare/verifycard/customscript/index.jsx
@@ -325,7 +325,7 @@
           </Col>
           <Col span={24} className="sql">
             <Form.Item label={
-              <Tooltip placement="topLeft" title={'鏁版嵁妫�鏌ユ浛鎹㈢ $check@ -> \'\'銆� @check$ -> \'\'锛孍rrorCode绛変簬C鏃� $check@ -> /*銆� @check$ -> */銆傛敞锛�1銆侀渶浣跨敤绯荤粺鎺ュ彛 2銆佽璁剧疆涓衡�滈�夋嫨澶氳鈥濇椂鏃犳晥銆�'}>
+              <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></>}>
                 <QuestionCircleOutlined className="mk-form-tip" />
                 sql
               </Tooltip>
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 069ae99..3786e6e 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -1517,7 +1517,7 @@
     return (
       <div>
         {card.label ? <div className="mk-com-name">{card.label} - 楠岃瘉淇℃伅</div> : null}
-        <Tabs activeKey={activeKey} className="verify-card-box" onChange={this.changeTab}>
+        <Tabs activeKey={activeKey} className="mk-verify-tabs" onChange={this.changeTab}>
           {verifyInter === 'system' || card.intertype === 'inner' ? <TabPane tab={
             <span>
               鍩虹楠岃瘉
diff --git a/src/templates/zshare/verifycard/index.scss b/src/templates/zshare/verifycard/index.scss
index f7f81d4..2f66da6 100644
--- a/src/templates/zshare/verifycard/index.scss
+++ b/src/templates/zshare/verifycard/index.scss
@@ -1,4 +1,7 @@
-.verify-card-box {
+.mk-verify-tabs {
+  .ant-tabs-nav .ant-tabs-tab {
+    margin-right: 25px;
+  }
   .ant-tabs-nav-scroll {
     text-align: center;
   }
@@ -226,4 +229,13 @@
     color: #1890ff;
     border-top: 1px solid #e9e9e9;
   }
+}
+
+@media screen and (max-width: 1500px) {
+  .mk-verify-tabs {
+    .ant-tabs-nav .ant-tabs-tab {
+      margin: 0 15px 0 0;
+      padding: 12px 12px;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index eca6187..fa7a65b 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -590,7 +590,7 @@
       }
   
       if (item.btnlog) {
-        item.btnlog = []
+        item.btnlog = null
       }
   
       let oriUids = {}
@@ -870,7 +870,7 @@
     }
 
     if (item.btnlog) {
-      item.btnlog = []
+      item.btnlog = null
     }
 
     let oriUids = {}
@@ -970,4 +970,167 @@
   }
   
   return JSON.parse(_style)
+}
+
+/**
+ * @description 鑾峰彇琛ㄥ悕
+ */
+export function getTables (config) {
+  let tables = []
+  let cuts = []
+  let cutreg = /(from|update|insert\s+into)\s+(@db@)?[a-z_]+/ig
+  let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
+
+  if (!config.wrap || !config.wrap.datatype || config.wrap.datatype === 'dynamic') {
+    if (config.setting.interType === 'system') {
+      if (config.setting.execute !== 'false') {
+        let tbs = config.setting.dataresource.match(cutreg)
+        tbs && cuts.push(...tbs)
+      }
+      config.scripts && config.scripts.forEach(script => {
+        if (script.status === 'false') return
+        let tbs = script.sql.match(cutreg)
+        tbs && cuts.push(...tbs)
+      })
+    } else {
+      let tb = config.setting.tableName.replace(/@db@|\s+/ig, '')
+      if (/[a-z_]+/ig.test(tb)) {
+        tables.push(tb)
+      }
+    }
+  }
+
+  let action = []
+
+  if (config.type === 'form') {
+    config.subcards.forEach(item => {
+      action.push(item.subButton)
+    })
+  } else if (config.subcards) {
+    config.subcards.forEach(item => {
+      item.elements.forEach(cell => {
+        if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+          action.push(cell)
+        }
+      })
+  
+      if (item.backElements && item.setting.type === 'multi') {
+        item.backElements.forEach(cell => {
+          if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+            action.push(cell)
+          }
+        })
+      }
+    })
+  }
+  config.cols && config.cols.forEach(col => {
+    if (col.type === 'action') {
+      col.elements.forEach(cell => {
+        if (['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+          action.push(cell)
+        }
+      })
+    }
+  })
+
+  config.elements && config.elements.forEach(cell => {
+    if (cell.eleType === 'button' && ['form', 'pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+      action.push(cell)
+    }
+  })
+
+  config.action && config.action.forEach(cell => {
+    if (['pop', 'prompt', 'exec', 'excelIn', 'excelOut'].includes(cell.OpenType)) {
+      action.push(cell)
+    }
+  })
+
+  action.forEach(btn => {
+    if (btn.OpenType === 'excelIn') {
+      if (!btn.verify) return
+      if (btn.intertype !== 'system' || btn.verify.default !== 'false') {
+        let tb = btn.sheet.replace(/@db@|\s+/ig, '')
+        if (/[a-z_]+/ig.test(tb)) {
+          tables.push(tb)
+        }
+      }
+      if (btn.intertype === 'system' && btn.verify.scripts) {
+        btn.verify.scripts.forEach(script => {
+          if (script.status === 'false') return
+          let tbs = script.sql.match(cutreg)
+          tbs && cuts.push(...tbs)
+        })
+      }
+    } else if (btn.OpenType === 'excelOut') {
+      if (btn.intertype !== 'system' || !btn.verify) return
+      if (btn.verify.dataType === 'custom') {
+        if (btn.verify.defaultSql !== 'false') {
+          let tbs = btn.verify.dataresource.match(cutreg)
+          tbs && cuts.push(...tbs)
+        }
+        btn.verify.scripts && btn.verify.scripts.forEach(script => {
+          if (script.status === 'false') return
+          let tbs = script.sql.match(cutreg)
+          tbs && cuts.push(...tbs)
+        })
+      }
+      if (btn.verify.enable === 'true' && btn.verify.script) {
+        let tbs = btn.verify.script.match(cutreg)
+        tbs && cuts.push(...tbs)
+      }
+    } else {
+      if (btn.intertype === 'inner') return
+      if (btn.intertype === 'outer' || btn.intertype === 'custom') {
+        if (btn.procMode === 'system' && btn.verify) {
+          if (btn.verify.default !== 'false' && btn.sql) {
+            let tb = btn.sql.replace(/@db@|\s+/ig, '')
+            if (/[a-z_]+/ig.test(tb)) {
+              tables.push(tb)
+            }
+          }
+          btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
+            if (script.status === 'false') return
+            let tbs = script.sql.match(cutreg)
+            tbs && cuts.push(...tbs)
+          })
+          btn.verify.scripts && btn.verify.scripts.forEach(script => {
+            if (script.status === 'false') return
+            let tbs = script.sql.match(cutreg)
+            tbs && cuts.push(...tbs)
+          })
+        }
+        if (btn.callbackType === 'script' && btn.verify) {
+          btn.verify.cbScripts && btn.verify.cbScripts.forEach(script => {
+            if (script.status === 'false') return
+            let tbs = script.sql.match(cutreg)
+            tbs && cuts.push(...tbs)
+          })
+        }
+      } else if (btn.verify) {
+        if (btn.verify.default !== 'false' && btn.sql) {
+          let tb = btn.sql.replace(/@db@|\s+/ig, '')
+          if (/[a-z_]+/ig.test(tb)) {
+            tables.push(tb)
+          }
+        }
+        btn.verify.customverifys && btn.verify.customverifys.forEach(script => {
+          if (script.status === 'false') return
+          let tbs = script.sql.match(cutreg)
+          tbs && cuts.push(...tbs)
+        })
+        btn.verify.scripts && btn.verify.scripts.forEach(script => {
+          if (script.status === 'false') return
+          let tbs = script.sql.match(cutreg)
+          tbs && cuts.push(...tbs)
+        })
+      }
+    }
+  })
+
+  cuts = cuts.map(item => item.replace(trimreg, ''))
+  tables.push(...cuts)
+  tables = tables.filter(Boolean)
+  tables = Array.from(new Set(tables))
+
+  return tables
 }
\ No newline at end of file
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index 1c66177..2e4dedc 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -446,7 +446,6 @@
    */
   static getPrevQueryParams (setting, search = [], BID) {
     let param = null
-
     if (setting.procMode !== 'inner') {
       param = this.getDefaultPrevQueryParam(setting, search, BID)
     } else {
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 3398cb7..208c78a 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -158,7 +158,7 @@
 
     let error = ''
     
-    sql = sql.replace(/sys\.fn_sqlvarbasetostr\(HashBytes\('MD5'/ig, '') // 璺宠繃MD5鍔犲瘑
+    sql = sql.replace(/sys\.fn_/ig, '') // 璺宠繃sys.fn_楠岃瘉
 
     chars.forEach(char => {
       if (!error && char.reg.test(sql)) {
@@ -1374,7 +1374,7 @@
  */
 export function getSysDefaultSql (btn, setting, formdata, param, data, columns, tab, retmsg = false, moduleParams, getOptions) {
   let primaryId = param.ID
-  let BID = param.BID
+  let BID = param.BID || ''
   let verify = btn.verify || {}
   let datavars = {}                 // 澹版槑鐨勫彉閲忥紝琛ㄥ崟鍙婃樉绀哄垪
   let _actionType = null
@@ -1434,14 +1434,11 @@
 
       if (form.type === 'number' || form.type === 'rate') {
         let val = form.value
-        if (typeof(val) !== 'number') {
-          val = parseFloat(val)
-          if (isNaN(val)) {
-            val = 0
-          }
+        if (isNaN(val)) {
+          val = 0
         }
         _initFormfields.push(`@${_key}=${val}`)
-      } else if (['date', 'datemonth', 'datetime'].includes(form.type)) {
+      } else if (['date', 'datemonth'].includes(form.type)) {
         _initFormfields.push(`@${_key}='${form.value || '1949-10-01'}'`)
       } else {
         _initFormfields.push(`@${_key}='${form.value}'`)
@@ -1476,7 +1473,7 @@
   }
 
   // 娣诲姞鏁版嵁涓瓧娈碉紝琛ㄥ崟鍊间紭鍏�(鎸夐挳涓嶉�夎鎴栧琛屾嫾鎺ユ椂璺宠繃)
-  if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce') {
+  if (data && btn.Ot !== 'notRequired' && btn.Ot !== 'requiredOnce' && columns && columns.length > 0) {
     datavars = {...data, ...datavars}
 
     const setField = (col) => {
@@ -1518,17 +1515,15 @@
       }
     }
 
-    if (columns && columns.length > 0) {
-      columns.forEach(col => {
-        if (col.type === 'colspan' || col.type === 'old_colspan') {
-          col.subcols.forEach(cell => {
-            setField(cell)
-          })
-        } else {
-          setField(col)
-        }
-      })
-    }
+    columns.forEach(col => {
+      if (col.type === 'colspan' || col.type === 'old_colspan') {
+        col.subcols.forEach(cell => {
+          setField(cell)
+        })
+      } else {
+        setField(col)
+      }
+    })
   }
 
   // 鍙橀噺澹版槑
@@ -1560,7 +1555,7 @@
   // 鍒濆鍖栧嚟璇佸強鐢ㄦ埛淇℃伅瀛楁
   _sql += `
       /* 鍑瘉鍙婄敤鎴蜂俊鎭垵濮嬪寲璧嬪�� */
-      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @BillCode='', @ModularDetailCode=''
+      select @BVoucher='',@FIBVoucherDate='',@FiYear='',@ErrorCode='',@retmsg='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}', @bid='${BID}', @BillCode='', @ModularDetailCode=''
       `
 
   // 琛ㄥ崟鍙橀噺璧嬪��
@@ -2069,6 +2064,20 @@
     _sql += _backCustomScript
   }
 
+  if (window.GLOB.breakpoint) {
+    let start = new RegExp('\\/\\*\\$breakpoint_begin_' + window.GLOB.breakpoint + '@', 'ig')
+    let end = new RegExp('@breakpoint_end_' + window.GLOB.breakpoint + '\\$\\*\\/', 'ig')
+
+    if (window.GLOB.breakpoint === 'all') {
+      start = /\/\*\$breakpoint_begin_[0-9a-z_]+@/ig
+      end = /@breakpoint_end_[0-9a-z_]+\$\*\//ig
+    }
+    
+    _sql = _sql.replace(start, '').replace(end, '').replace(/\$breakpoint_proc@/ig, window.GLOB.breakpoint)
+    _sql += `
+      z_debug_end: select @ErrorCode='E',@retmsg='debug_end' goto aaa`
+  }
+
   if (retmsg) {
     _sql += `
       aaa: if @ErrorCode!=''
@@ -2082,7 +2091,7 @@
   }
 
   _sql = _sql.replace(/@ID@/ig, `'${primaryId || ''}'`)
-  _sql = _sql.replace(/@BID@/ig, `'${BID || ''}'`)
+  _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') || ''}'`)
@@ -2095,7 +2104,7 @@
 
   if (retmsg) {
     _callbacksql = _callbacksql.replace(/@ID@/ig, `'${primaryId || ''}'`)
-    _callbacksql = _callbacksql.replace(/@BID@/ig, `'${BID || ''}'`)
+    _callbacksql = _callbacksql.replace(/@BID@/ig, `'${BID}'`)
     _callbacksql = _callbacksql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
     _callbacksql = _callbacksql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
     _callbacksql = _callbacksql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
diff --git a/src/views/appmanage/index.jsx b/src/views/appmanage/index.jsx
index 931230a..a3512bd 100644
--- a/src/views/appmanage/index.jsx
+++ b/src/views/appmanage/index.jsx
@@ -709,8 +709,9 @@
     if (item.typename === 'pc') {
       route = 'pcdesign'
     }
+    let param = {...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'}
 
-    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...item, kei_no: selectApp.kei_no, remark: selectApp.remark, type: 'app'})))}`))
+    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify(param)))}`))
   }
 
   jumpMenu = (item) => {
diff --git a/src/views/design/sidemenu/editthdmenu/index.jsx b/src/views/design/sidemenu/editthdmenu/index.jsx
index 8d12124..8e71109 100644
--- a/src/views/design/sidemenu/editthdmenu/index.jsx
+++ b/src/views/design/sidemenu/editthdmenu/index.jsx
@@ -307,7 +307,6 @@
 
 const mapStateToProps = (state) => {
   return {
-    mainMenu: state.mainMenu,
     menuTree: state.menuTree
   }
 }
diff --git a/src/views/imdesign/index.jsx b/src/views/imdesign/index.jsx
index 15ee914..3092a93 100644
--- a/src/views/imdesign/index.jsx
+++ b/src/views/imdesign/index.jsx
@@ -55,10 +55,9 @@
 
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
+        sessionStorage.setItem('appName', param.remark || '')
         sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
-        sessionStorage.setItem('role_type', param.role_type || 'true')
-        sessionStorage.setItem('login_types', param.login_types || 'false')
         sessionStorage.setItem('typename', param.typename || 'mob')
         sessionStorage.setItem('adapter', param.adapter || '')
         sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
diff --git a/src/views/main/index.jsx b/src/views/main/index.jsx
index 257b4b8..d13a74c 100644
--- a/src/views/main/index.jsx
+++ b/src/views/main/index.jsx
@@ -23,6 +23,21 @@
 
   componentDidMount () {
     MKEmitter.addListener('resetSelectLine', this.resetParentParam)
+
+    Object.defineProperty(window, 'debug', {
+      set(value) {
+        if (value + '' === 'false') {
+          window.debugger = false
+          window.GLOB.breakpoint = false
+          sessionStorage.removeItem('breakpoint')
+        } else {
+          window.debugger = true
+          window.GLOB.breakpoint = value + ''
+          sessionStorage.setItem('breakpoint', value)
+        }
+        MKEmitter.emit('debugChange')
+      }
+    })
   }
 
   componentWillUnmount () {
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index 063842e..357f02f 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -7,6 +7,7 @@
 import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
 import html2canvas from 'html2canvas'
+import md5 from 'md5'
 
 import Api from '@/api'
 import options from '@/store/options.js'
@@ -39,6 +40,7 @@
 const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
 const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
 const Versions = asyncComponent(() => import('@/menu/versions'))
+const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
 const SysInterface = asyncComponent(() => import('@/menu/sysinterface'))
 const UrlFieldComponent = asyncComponent(() => import('@/menu/urlfieldcomponent'))
 const PictureController = asyncComponent(() => import('@/menu/picturecontroller'))
@@ -108,7 +110,6 @@
   componentDidMount () {
     MKEmitter.addListener('delButtons', this.delButtons)
     MKEmitter.addListener('modalStatus', this.modalStatus)
-    // MKEmitter.addListener('thawButtons', this.thawButtons)
     MKEmitter.addListener('copyButtons', this.copyButtons)
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
@@ -179,7 +180,6 @@
     }
     MKEmitter.removeListener('delButtons', this.delButtons)
     MKEmitter.removeListener('modalStatus', this.modalStatus)
-    // MKEmitter.removeListener('thawButtons', this.thawButtons)
     MKEmitter.removeListener('copyButtons', this.copyButtons)
     MKEmitter.removeListener('changePopview', this.initPopview)
     MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
@@ -355,10 +355,6 @@
   copyButtons = (items) => {
     this.setState({copyButtons: [...this.state.copyButtons, ...items]})
   }
-  
-  // thawButtons = (item) => {
-  //   this.setState({thawButtons: [...this.state.thawButtons, item]})
-  // }
 
   initPopview = (card, btn) => {
     const { oriConfig, config } = this.state
@@ -483,13 +479,16 @@
     })
   }
 
-  getMenuMessage = (delButtons) => {
+  getMenuMessage = (delButtons, tbs) => {
     const { config } = this.state
     let buttons = []
     let _sort = 1
 
     let traversal = (components) => {
       components.forEach(item => {
+        if (item.$tables) {
+          tbs.push(...item.$tables)
+        }
         if (item.type === 'tabs') {
           item.subtabs.forEach(tab => {
             traversal(tab.components)
@@ -621,6 +620,37 @@
         config.enabled = false
       }
 
+      let tbs = []
+      let delButtons = fromJS(this.state.delButtons).toJS()
+      let btns = this.getMenuMessage(delButtons, tbs)
+      let arr = []
+      tbs = tbs.filter(tb => {
+        let _tb = tb.toLowerCase()
+
+        if (arr.includes(_tb)) return false
+        arr.push(_tb)
+
+        return true
+      })
+      tbs.sort()
+      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
+        let names = sessionStorage.getItem('mk_tb_names')
+        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+      }
+      tbs = tbs.map(tb => `'${tb}'`).join(';')
+
+      let key = md5(config.uuid + tbs.toLowerCase())
+      let url = ''
+
+      if (config.tbkey === key) {
+        key = ''
+      } else {
+        let urlparam = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
+        urlparam.type = 'admin'
+        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+        config.tbkey = key
+      }
+
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
         FstID: config.fstMenuId || '',
@@ -632,10 +662,13 @@
         Template: 'CustomPage',
         MenuName: config.MenuName || '',
         PageParam: JSON.stringify({Template: 'CustomPage', OpenType: config.OpenType || 'newtab', hidden: config.hidden || 'false'}),
-        LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config))),
         open_edition: config.open_edition,
         LText: '',
-        LTexttb: ''
+        LTexttb: '',
+        debug_md5: key,
+        debug_url: url,
+        debug_list: window.btoa(tbs),
+        LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(config)))
       }
 
       param.LText = Utils.formatOptions(param.LText)
@@ -653,10 +686,9 @@
         LText: []
       }
 
-      let delButtons = fromJS(this.state.delButtons).toJS()
       let btnIds = '' // 鐢ㄤ簬澶嶅埗鎸夐挳鐨勮繃婊�
       if (MenuType !== 'billPrint') {
-        btnParam.LText = this.getMenuMessage(delButtons)
+        btnParam.LText = btns
         btnParam.LText = btnParam.LText.join(' union all ')
 
         btnIds = btnParam.LText
@@ -728,28 +760,6 @@
           }
           return Api.getSystemConfig(_param)
         }
-      // }).then(res => { // 鎸夐挳瑙i櫎鍐荤粨
-      //   if (!res) return
-      //   if (!res.status) {
-      //     notification.warning({
-      //       top: 92,
-      //       message: res.message,
-      //       duration: 5
-      //     })
-      //     return false
-      //   }
-
-      //   let ids = thawButtons.filter(item => btnIds.indexOf(item) !== -1)
-      //   if (ids.length === 0) {
-      //     return {
-      //       status: true
-      //     }
-      //   } else {
-      //     return Api.getSystemConfig({
-      //       func: 'sPC_MainMenu_ReDel',
-      //       MenuID: ids.join(',')
-      //     })
-      //   }
       }).then(res => { // 椤甸潰淇濆瓨
         if (!res) return
 
@@ -1130,12 +1140,11 @@
                 </Collapse>
               </div>
               <div className={'menu-view' + (menuloading ? ' saving' : '') + (eyeopen ? ' eye-open' : '')}>
-                <Card title={
-                  <div style={{paddingLeft: '15px'}}> {config && config.MenuName} </div>
-                } bordered={false} extra={
-                  <div>
+                <Card title={config ? config.MenuName : ''} bordered={false} extra={
+                  <div className="mk-opeartion-list">
                     <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
                     <Versions MenuId={MenuId} open_edition={config ? config.open_edition : ''}/>
+                    <TableNodes config={config} />
                     <ReplaceField type="custom" config={config} updateConfig={this.resetConfig}/>
                     <SysInterface config={config} updateConfig={this.updateConfig}/>
                     <PictureController/>
diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss
index 6e9f063..4c68c97 100644
--- a/src/views/menudesign/index.scss
+++ b/src/views/menudesign/index.scss
@@ -219,4 +219,16 @@
     background: transparent!important;
     border-radius: 0!important;
   }
+}
+
+@media screen and (max-width: 1500px) {
+  .mk-opeartion-list .ant-btn {
+    min-width: 65px;
+    .anticon {
+      display: none;
+    }
+    .anticon + span {
+      margin-left: 0px;
+    }
+  }
 }
\ No newline at end of file
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index 8e6f9a1..7d19e54 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -2,16 +2,16 @@
 import { DndProvider } from 'react-dnd'
 import { withRouter } from 'react-router'
 import { is, fromJS } from 'immutable'
-import moment from 'moment'
 import HTML5Backend from 'react-dnd-html5-backend'
 import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
+import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils, { setGLOBFuncs } from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/mob.js'
 import enUS from '@/locales/en-US/mob.js'
-import antdEnUS from 'antd/es/locale/en_US'
 import antdZhCN from 'antd/es/locale/zh_CN'
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
@@ -33,6 +33,7 @@
 const ViewNodes = asyncComponent(() => import('@/menu/viewnodes'))
 const SourceWrap = asyncComponent(() => import('@/mob/modulesource'))
 const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
+const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
 const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
 const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
 const SysInterface = asyncComponent(() => import('@/menu/sysinterface'))
@@ -61,7 +62,6 @@
 
 class MobDesign extends Component {
   state = {
-    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
     dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loading: true,
     MenuId: '',
@@ -89,10 +89,9 @@
 
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
+        sessionStorage.setItem('appName', param.remark || '')
         sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
-        sessionStorage.setItem('role_type', param.role_type || 'true')
-        sessionStorage.setItem('login_types', param.login_types || 'false')
         sessionStorage.setItem('typename', param.typename || 'mob')
         sessionStorage.setItem('adapter', param.adapter || '')
         sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
@@ -100,7 +99,6 @@
         sessionStorage.setItem('instantMessage', param.instantMessage || '')
 
         this.setState({
-          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
           dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
         })
         this.getAppMessage(param.MenuID)
@@ -664,7 +662,7 @@
             backElements: []
           }
         ],
-        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
+        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
         wrap: {name: 'logo', width: 24, datatype: 'static', cardType: '', blacklist: []},
         name: 'logo', floor: 1, switchable: true,
         setting:{interType: 'system'}, tabId: '', style:{paddingTop: '8vh', paddingBottom: '10vh'}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
@@ -696,7 +694,7 @@
             backElements: []
           }
         ],
-        headerStyle: {}, parentId: '', width: 24, scripts: [], btnlog: [], pageable: false,
+        headerStyle: {}, parentId: '', width: 24, scripts: [], pageable: false,
         wrap: {name: 'Power', width: 24, datatype: 'static', cardType: '', blacklist: []},
         name: 'Power', floor: 1, switchable: true,
         setting:{interType: 'system'}, tabId: '', style:{}, dataName: Utils.getuuid(), format: 'object', subtype: 'propcard', type: 'card', uuid: Utils.getuuid(), columns: []
@@ -919,12 +917,16 @@
     })
   }
 
-  getMenuMessage = () => {
+  getMenuMessage = (tbs) => {
     const { config } = this.state
     
     let traversal = (components) => {
       let list = []
       components.forEach(item => {
+        if (item.$tables) {
+          tbs.push(...item.$tables)
+        }
+
         let m = {
           key: item.uuid,
           title: item.name,
@@ -1320,10 +1322,50 @@
         config.enabled = false
       }
 
+      let tbs = []
       let roleParam = {type: 'view', version: '1.0', key: config.uuid, title: config.MenuName, children: []}
-      roleParam.children = this.getMenuMessage()
+      roleParam.children = this.getMenuMessage(tbs)
       config.loginview = false
       config.tabview = false
+
+      let arr = []
+      tbs = tbs.filter(tb => {
+        let _tb = tb.toLowerCase()
+
+        if (arr.includes(_tb)) return false
+        arr.push(_tb)
+
+        return true
+      })
+      tbs.sort()
+      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
+        let names = sessionStorage.getItem('mk_tb_names')
+        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+      }
+      tbs = tbs.map(tb => `'${tb}'`).join(';')
+
+      let key = md5(config.uuid + sessionStorage.getItem('kei_no') + sessionStorage.getItem('typename') + sessionStorage.getItem('lang') + tbs.toLowerCase())
+      let url = ''
+
+      if (config.tbkey === key) {
+        key = ''
+      } else {
+        let urlparam = {
+          type: 'app',
+          MenuID: config.uuid,
+          ID: sessionStorage.getItem('appId') || '',
+          remark: sessionStorage.getItem('appName') || '',
+          lang: sessionStorage.getItem('lang') || '',
+          kei_no: sessionStorage.getItem('kei_no') || '',
+          typename: sessionStorage.getItem('typename') || '',
+          adapter: sessionStorage.getItem('adapter') || '',
+          sysBgColor: sessionStorage.getItem('sysBgColor') || '',
+          MenuName: config.MenuName || '',
+        }
+
+        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+        config.tbkey = key
+      }
 
       if (roleParam.children.length === 0) {
         roleParam.pass = true
@@ -1377,7 +1419,10 @@
         menus_rolelist: window.btoa(window.encodeURIComponent(JSON.stringify(roleParam))),
         LText: '',
         LTexttb: '',
-        menus_used_list
+        menus_used_list,
+        debug_md5: key,
+        debug_url: url,
+        debug_list: window.btoa(tbs)
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1921,10 +1966,10 @@
 
 
   render () {
-    const { viewType, localedict, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters, eyeopen } = this.state
+    const { viewType, comloading, loading, settingshow, controlshow, activeKey, dict, MenuId, config, menuloading, customComponents, adapters, eyeopen } = this.state
 
     return (
-      <ConfigProvider locale={localedict}>
+      <ConfigProvider locale={antdZhCN}>
         <div className={'mk-mob-view ' + viewType} id="mk-mob-design-view">
           <Header changeView={this.changeView}/>
           {loading ? <Spin className="view-spin" size="large" /> : null}
@@ -1979,6 +2024,7 @@
                 <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
                 <CreateView resetmenu={this.getAppMenus} />
                 <PasteController insert={this.insert} />
+                <TableNodes config={config} />
                 <ViewNodes config={config} MenuId={MenuId}/>
                 <SysInterface config={config} updateConfig={this.updateConfig}/>
                 <PictureController/>
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index 26c4531..17f63bf 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -2,16 +2,17 @@
 import { DndProvider } from 'react-dnd'
 import { withRouter } from 'react-router'
 import { is, fromJS } from 'immutable'
-import moment from 'moment'
 import HTML5Backend from 'react-dnd-html5-backend'
 import { ConfigProvider, notification, Modal, Collapse, Switch, Button, message, Spin, Typography } from 'antd'
 import { DoubleLeftOutlined, DoubleRightOutlined, HomeOutlined, LoginOutlined, RedoOutlined, ArrowLeftOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
+import moment from 'moment'
+import md5 from 'md5'
 
 import Api from '@/api'
 import Utils, { setGLOBFuncs } from '@/utils/utils.js'
 import zhCN from '@/locales/zh-CN/mob.js'
 import enUS from '@/locales/en-US/mob.js'
-import antdEnUS from 'antd/es/locale/en_US'
+// import antdEnUS from 'antd/es/locale/en_US'
 import antdZhCN from 'antd/es/locale/zh_CN'
 import MKEmitter from '@/utils/events.js'
 import MenuUtils from '@/utils/utils-custom.js'
@@ -31,6 +32,7 @@
 const ViewNodes = asyncComponent(() => import('@/menu/viewnodes'))
 const SourceWrap = asyncComponent(() => import('@/pc/modulesource'))
 const Modulecell = asyncComponent(() => import('@/menu/modulecell'))
+const TableNodes = asyncComponent(() => import('@/menu/tablenodes'))
 const CreateView = asyncComponent(() => import('@/pc/createview'))
 const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
 const Quotecomponent = asyncComponent(() => import('@/pc/quotecomponent'))
@@ -55,7 +57,6 @@
 
 class MenuDesign extends Component {
   state = {
-    localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
     dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     loading: true,
     MenuId: '',
@@ -91,14 +92,12 @@
 
       if (param.type === 'app') {
         sessionStorage.setItem('appId', param.ID || '')
+        sessionStorage.setItem('appName', param.remark || '')
         sessionStorage.setItem('lang', param.lang || 'zh-CN')
         sessionStorage.setItem('kei_no', param.kei_no || '')
-        sessionStorage.setItem('role_type', param.role_type || 'true')
-        sessionStorage.setItem('login_types', param.login_types || 'false')
         sessionStorage.setItem('sysBgColor', param.sysBgColor || '#ffffff')
 
         this.setState({
-          localedict: sessionStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS,
           dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
         })
         this.getAppMessage(param.MenuID)
@@ -869,7 +868,7 @@
     })
   }
 
-  getMenuMessage = () => {
+  getMenuMessage = (tbs) => {
     const { config } = this.state
     let nodes = {type: 'view', version: '1.0', key: config.uuid, title: config.MenuName, children: []}
     let popviews = []
@@ -877,6 +876,10 @@
     let traversal = (components) => {
       let list = []
       components.forEach(item => {
+        if (item.$tables) {
+          tbs.push(...item.$tables)
+        }
+
         let m = {
           key: item.uuid,
           title: item.name,
@@ -1204,11 +1207,50 @@
         config.enabled = false
       }
 
-      let roleParam = this.getMenuMessage()
+      let tbs = []
+      let roleParam = this.getMenuMessage(tbs)
 
       let subMenus = this.getSubMenus()
       let menus_used_list = subMenus.map(m => `'${config.uuid}','${config.MenuName || ''}','${config.MenuNo || ''}','${m.MenuID}','${m.MenuName}'`).join(';')
       menus_used_list = window.btoa(window.encodeURIComponent(menus_used_list || 'del'))
+
+      let arr = []
+      tbs = tbs.filter(tb => {
+        let _tb = tb.toLowerCase()
+
+        if (arr.includes(_tb)) return false
+        arr.push(_tb)
+
+        return true
+      })
+      tbs.sort()
+      if (tbs.length && sessionStorage.getItem('mk_tb_names')) {
+        let names = sessionStorage.getItem('mk_tb_names')
+        tbs = tbs.filter(tb => names.indexOf(',' + tb.toLowerCase() + ',') > -1)
+      }
+      tbs = tbs.map(tb => `'${tb}'`).join(';')
+
+      let key = md5(config.uuid + sessionStorage.getItem('kei_no') + 'pc' + sessionStorage.getItem('lang') + tbs.toLowerCase())
+      let url = ''
+
+      if (config.tbkey === key) {
+        key = ''
+      } else {
+        let urlparam = {
+          type: 'app',
+          MenuID: config.uuid,
+          ID: sessionStorage.getItem('appId') || '',
+          remark: sessionStorage.getItem('appName') || '',
+          lang: sessionStorage.getItem('lang') || '',
+          kei_no: sessionStorage.getItem('kei_no') || '',
+          typename: 'pc',
+          sysBgColor: sessionStorage.getItem('sysBgColor') || '',
+          MenuName: config.MenuName || '',
+        }
+
+        url = window.btoa(window.encodeURIComponent(JSON.stringify(urlparam)))
+        config.tbkey = key
+      }
 
       let param = {
         func: 'sPC_TrdMenu_AddUpt',
@@ -1227,7 +1269,10 @@
         open_edition: config.open_edition,
         LText: '',
         LTexttb: '',
-        menus_used_list
+        menus_used_list,
+        debug_md5: key,
+        debug_url: url,
+        debug_list: window.btoa(tbs)
       }
 
       param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
@@ -1830,10 +1875,10 @@
   }
 
   render () {
-    const { localedict, loading, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents, eyeopen } = this.state
+    const { loading, comloading, activeKey, settingshow, controlshow, dict, MenuId, config, menuloading, customComponents, eyeopen } = this.state
 
     return (
-      <ConfigProvider locale={localedict}>
+      <ConfigProvider locale={antdZhCN}>
         <div className={'mk-pc-view '} id="mk-pc-design-view">
           {loading ? <Spin className="view-spin" size="large" /> : null}
           <DndProvider backend={HTML5Backend}>
@@ -1886,6 +1931,7 @@
                 <Button className="mk-border-purple" onClick={() => this.setState({eyeopen: !eyeopen})}>{!eyeopen ? <EyeOutlined /> : <EyeInvisibleOutlined />} 缁勪欢鍚�</Button>
                 <CreateView resetmenu={this.getAppMenus} />
                 <PasteController insert={this.insert} />
+                <TableNodes config={config} />
                 <ViewNodes config={config} MenuId={MenuId}/>
                 <SysInterface config={config} updateConfig={this.updateConfig}/>
                 <PictureController/>
diff --git a/src/views/systemfunc/header/index.jsx b/src/views/systemfunc/header/index.jsx
index 1d793a5..c146a84 100644
--- a/src/views/systemfunc/header/index.jsx
+++ b/src/views/systemfunc/header/index.jsx
@@ -32,13 +32,13 @@
       <header className="sys-header-container ant-menu-dark">
         <div className="header-logo"><img src={MainLogo} alt=""/></div>
         <div className="title">HS</div>
-        <div className="close" onClick={() => window.close()}>鍏抽棴</div>
         <div className="header-setting">
           <img src={this.state.avatar} alt=""/>
           <span>
             <span className="username">{this.state.userName}</span>
           </span>
         </div>
+        <div className="close" onClick={() => window.close()}>鍏抽棴</div>
       </header>
     )
   }
diff --git a/src/views/systemfunc/header/index.scss b/src/views/systemfunc/header/index.scss
index 5311911..9cd8426 100644
--- a/src/views/systemfunc/header/index.scss
+++ b/src/views/systemfunc/header/index.scss
@@ -31,11 +31,11 @@
   }
 
   .close {
-    position: absolute;
+    float: right;
     font-size: 16px;
     color: #ffffff;
-    right: 90px;
-    top: 12px;
+    margin-top: 13px;
+    margin-right: 15px;
     cursor: pointer;
   }
 

--
Gitblit v1.8.0