From 669d7cc31eb3728ad09bfb7ce6e615f5c571c14e Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 08 一月 2020 15:58:39 +0800
Subject: [PATCH] 2020-01-08

---
 src/templates/modalviewconfig/tabdragelement/index.jsx     |  114 +
 src/templates/modalviewconfig/index.jsx                    | 3132 ++++++++++++++++++++++++++++++
 src/templates/modalviewconfig/tabdragelement/card.jsx      |   41 
 src/templates/tableshare/verifycard/customform/index.jsx   |    6 
 src/templates/tableshare/verifycard/voucherform/index.jsx  |   74 
 src/templates/modalviewconfig/source.jsx                   |  375 +++
 src/templates/modalconfig/settingform/index.jsx            |   12 
 src/templates/modalviewconfig/actionform/index.scss        |   33 
 src/templates/modalviewconfig/index.scss                   |  515 +++++
 src/tabviews/tableshare/actionList/index.jsx               |   70 
 src/templates/modalconfig/modalform/index.jsx              |   19 
 src/templates/modalconfig/index.jsx                        |   58 
 src/templates/modalviewconfig/settingform/index.jsx        |  312 +++
 src/templates/modalviewconfig/settingform/index.scss       |   14 
 src/templates/modalconfig/source.jsx                       |    9 
 src/templates/modalviewconfig/tabform/index.scss           |    7 
 src/templates/tableshare/verifycard/uniqueform/index.jsx   |   40 
 src/templates/modalviewconfig/tabdragelement/index.scss    |   21 
 src/tabviews/commontable/index.jsx                         |    4 
 src/templates/tableshare/verifycard/index.jsx              |   67 
 src/templates/tableshare/verifycard/billcodeform/index.jsx |  244 +
 src/templates/modalviewconfig/tabform/index.jsx            |  227 ++
 src/utils/utils.js                                         |  163 +
 src/templates/modalviewconfig/actionform/index.jsx         |  510 +++++
 24 files changed, 5,770 insertions(+), 297 deletions(-)

diff --git a/src/tabviews/commontable/index.jsx b/src/tabviews/commontable/index.jsx
index c9d7e50..b7e8f63 100644
--- a/src/tabviews/commontable/index.jsx
+++ b/src/tabviews/commontable/index.jsx
@@ -693,8 +693,8 @@
           <div className="main-table-box">
             {isLinkMain ?
               <div className="pickchange">
-                {setting.tableType === 'checkbox' ? <Switch title="鍗曢�夊垏鎹�" checkedChildren="澶�" unCheckedChildren="鍗�" defaultChecked={setsingle} onChange={this.checkChange} /> : null}
-                {this.state.BIDs.mainTable && (setting.tableType === 'radio' || setsingle) ? <Switch title="鏀惰捣" checkedChildren="鍏�" unCheckedChildren="寮�" defaultChecked={pickup} onChange={this.pickupChange} /> : null}
+                {setting.tableType === 'checkbox' ? <Switch title="鍗曢�夊垏鎹�" checkedChildren="鍗�" unCheckedChildren="澶�" defaultChecked={setsingle} onChange={this.checkChange} /> : null}
+                {this.state.BIDs.mainTable && (setting.tableType === 'radio' || setsingle) ? <Switch title="鏀惰捣" checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={pickup} onChange={this.pickupChange} /> : null}
               </div> : null
             }
             <MainTable
diff --git a/src/tabviews/tableshare/actionList/index.jsx b/src/tabviews/tableshare/actionList/index.jsx
index 0b85658..0c22ac1 100644
--- a/src/tabviews/tableshare/actionList/index.jsx
+++ b/src/tabviews/tableshare/actionList/index.jsx
@@ -131,18 +131,31 @@
         return
       }
 
+      // 鎵ц鏂瑰紡涓哄琛屾嫾鎺ワ紝涓旀墦寮�鏂瑰紡涓鸿〃鍗曟椂锛屼細杞负寰幆鍙戦�佽姹�
+      // 鎵撳紑鏂瑰紡涓烘ā鎬佹锛屼娇鐢ㄥ唴閮ㄥ嚱鏁版坊鍔�
       if (
         btn.Ot === 'notRequired' ||
         btn.Ot === 'requiredSgl' ||
         (btn.Ot === 'requiredOnce' && btn.OpenType !== 'pop') ||
         (btn.OpenType === 'pop' && !btn.innerFunc && btn.sql && btn.sqlType === 'insert')
       ) {
+
+        // 鍒涘缓鍑瘉鏃讹紝闇�瑕侀�夋嫨琛屾椂
+        if (data.length === 0 && !btn.innerFunc && btn.verify && btn.verify.voucher && btn.verify.voucher.enabled) {
+          notification.warning({
+            top: 92,
+            message: '浣跨敤鍒涘缓鍑瘉鍑芥暟锛岄渶瑕侀�夋嫨琛岋紒',
+            duration: 10
+          })
+          return
+        }
+
         let param = { // 绯荤粺瀛樺偍杩囩▼
           func: 'sPC_TableData_InUpDe',
           BID: this.props.BID
         }
 
-        if (setting.primaryKey) {
+        if (setting.primaryKey) { // 涓婚敭鍊奸璁撅紝浠庤〃鏍兼暟鎹涓�椤归�夊彇
           param[setting.primaryKey] = (data[0] && data[0][setting.primaryKey]) || ''
         }
 
@@ -152,7 +165,7 @@
             
           } else if (btn.Ot === 'requiredSgl') {
             ID = data[0][setting.primaryKey]
-          } else if (btn.Ot === 'requiredOnce') {
+          } else if (btn.Ot === 'requiredOnce') { // id鍊兼嫾鎺�
             let ids = data.map(d => { return d[setting.primaryKey]})
             ID = ids.join(',')
           }
@@ -161,10 +174,10 @@
             param[setting.primaryKey] = ID
           }
 
-          if (btn.innerFunc) {
+          if (btn.innerFunc) { // 浣跨敤鑷畾涔夊嚱鏁�
             param.func = btn.innerFunc
           } else if (btn.sql) {
-            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, '', param[setting.primaryKey])) // 鏁版嵁婧�
+            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, '', param[setting.primaryKey], data[0])) // 鏁版嵁婧�
             param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
             param.secretkey = Utils.encrypt(param.LText, param.timestamp)
           }
@@ -176,16 +189,16 @@
               param[_data.key] = _data.value
             })
 
-          } else if (btn.sql && btn.sqlType === 'insert') {
+          } else if (btn.sql && btn.sqlType === 'insert') { // 绯荤粺鍑芥暟娣诲姞鏃讹紝鐢熸垚uuid
             if (setting.primaryKey) {
               param[setting.primaryKey] = Utils.getguid()
             }
 
-            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey])) // 鏁版嵁婧�
+            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey], data[0])) // 鏁版嵁婧�
             param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
             param.secretkey = Utils.encrypt(param.LText, param.timestamp)
           } else if (btn.sql) {
-            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey])) // 鏁版嵁婧�
+            param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey], data[0])) // 鏁版嵁婧�
             param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
             param.secretkey = Utils.encrypt(param.LText, param.timestamp)
           }
@@ -216,7 +229,7 @@
             if (btn.innerFunc) {
               param.func = btn.innerFunc
             } else if (btn.sql) {
-              param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, '', param[setting.primaryKey])) // 鏁版嵁婧�
+              param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, '', param[setting.primaryKey], cell)) // 鏁版嵁婧�
               param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
               param.secretkey = Utils.encrypt(param.LText, param.timestamp)
             }
@@ -232,7 +245,7 @@
               if (setting.primaryKey) {
                 param[setting.primaryKey] = cell[setting.primaryKey]
               }
-              param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey])) // 鏁版嵁婧�
+              param.LText = Utils.formatOptions(Utils.getSysDefaultSql(btn, setting, formdata, param[setting.primaryKey], cell)) // 鏁版嵁婧�
               param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
               param.secretkey = Utils.encrypt(param.LText, param.timestamp)
             }
@@ -666,6 +679,14 @@
     const { configMap, execAction } = this.state
     let subfields = []
 
+    if (execAction.setting.display === 'prompt') { // 濡傛灉琛ㄥ崟浠ユ槸鍚︽灞曠ず锛屼笉璇锋眰涓嬫媺鑿滃崟淇℃伅
+      this.setState({
+        btnloading: false
+      })
+      this.modelconfirm()
+      return
+    }
+
     if (execAction.groups.length > 0) {
       execAction.groups.forEach(group => {
         group.sublist.forEach(field => {
@@ -788,6 +809,37 @@
     })
   }
 
+  modelconfirm = () => {
+    const { execAction, tabledata } = this.state
+    let _this = this
+    let _fields = []
+    if (execAction.groups.length > 0) {
+      execAction.groups.forEach(group => {
+        _fields = [..._fields, ...group.sublist]
+      })
+    } else {
+      _fields = execAction.fields
+    }
+    let result = _fields.map(item => {
+      return {
+        key: item.field,
+        readonly: item.readonly === 'true',
+        type: item.type,
+        value: item.initval
+      }
+    })
+
+    confirm({
+      title: this.props.dict['main.action.confirm.tip'],
+      onOk() {
+        return new Promise(resolve => {
+          _this.execSubmit(execAction, tabledata, resolve, result)
+        })
+      },
+      onCancel() {}
+    })
+  }
+
   /**
    * @description 鏄剧ず妯℃�佹
    */
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index cbd7f55..79654ca 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -53,9 +53,7 @@
     selectedTables: [],    // 宸查�夎〃鍚�
     originConfig: null,    // 鍘熷鑿滃崟
     groupVisible: false,   // 鍏ㄥ眬閰嶇疆妯℃�佹
-    curgroup: null,        // 褰撳墠缁勶紝鏂板缓鎴栫紪杈�
-    formItems: [],         // 琛ㄥ崟鍙�夌被鍨�
-    billCodes: null        // 鎸夐挳涓畾涔夌殑鍗曞彿鐢熸垚鍑芥暟瀛楁闆�
+    curgroup: null         // 褰撳墠缁勶紝鏂板缓鎴栫紪杈�
   }
 
   /**
@@ -90,21 +88,9 @@
     // 涓昏彍鍗曞凡鏈夐�夋嫨鐨勮〃鍚嶏紝妯℃�佹娌℃湁琛ㄥ悕鏃讹紝澶嶅埗涓昏彍鍗曡〃鍚�
     _config.tables = _config.tables.length === 0 ? _menu.tables : _config.tables
 
-    let _formItems = JSON.parse(JSON.stringify((Source.searchItems)))
-    if (editAction && editAction.intertype === 'inner' && !editAction.innerFunc) {
-      _formItems.push({
-        type: 'form',
-        label: '鍑芥暟鍙橀噺',
-        subType: 'funcvar',
-        url: ''
-      })
-    }
-    
     this.setState({
       menu: _menu,
       config: _config,
-      formItems: _formItems,
-      billCodes: editAction && editAction.verify && editAction.verify.billcodes ? editAction.verify.billcodes : [],
       selectedTables: _config.tables || [],
       originConfig: JSON.parse(JSON.stringify(_config)),
       modalformlist: [
@@ -328,8 +314,6 @@
    * 3銆佽缃紪杈戝弬鏁伴」-formlist
    */
   handleForm = (card) => {
-    const { billCodes } = this.state
-
     this.setState({
       visible: true,
       card: card,
@@ -515,18 +499,6 @@
             value: 'false',
             text: this.state.dict['header.form.false']
           }]
-        },
-        {
-          type: 'select',
-          key: 'linkfield',
-          label: '鍏宠仈鍙橀噺',
-          initVal: card.linkfield || '',
-          required: true,
-          options: billCodes.map(code => {
-            code.value = code.field
-            code.text = code.field
-            return code
-          })
         }
       ]
     })
@@ -613,7 +585,7 @@
   submitConfig = () => {
     const { editAction } = this.props
     const { config, menu } = this.state
-      
+
     if ((!config.groups[0] && !config.fields[0]) || (config.fields[0] && config.fields[0].origin)) {
       notification.warning({
         top: 92,
@@ -621,6 +593,27 @@
         duration: 10
       })
       return
+    }
+
+    if (config.setting.display === 'prompt') {
+      let _fields = []
+      if (config.groups.length > 0) {
+        config.groups.forEach(group => {
+          _fields = [..._fields, ...group.sublist]
+        })
+      } else {
+        _fields = config.fields
+      }
+  
+      let readfields = _fields.filter(item => item.initval || item.initval === 0)
+      if (readfields.length < _fields.length) {
+        notification.warning({
+          top: 92,
+          message: '浠ャ�婃槸鍚︽銆嬫樉绀虹殑寮规锛屾墍鏈夎〃鍗曞繀椤诲惈鏈夐粯璁ゅ�硷紒',
+          duration: 10
+        })
+        return
+      }
     }
 
     let _LongParam = ''
@@ -1088,7 +1081,7 @@
   }
 
   render () {
-    const { menu, config, formItems } = this.state
+    const { menu, config } = this.state
 
     return (
       <div className="modal-form-board">
@@ -1135,7 +1128,7 @@
               </Panel>
               <Panel header={this.state.dict['header.menu.form']} key="1">
                 <div className="search-element">
-                  {formItems.map((item, index) => {
+                  {Source.searchItems.map((item, index) => {
                     return (<SourceElement key={index} content={item}/>)
                   })}
                 </div>
@@ -1221,7 +1214,6 @@
           {<ModalForm
             dict={this.state.dict}
             card={this.state.card}
-            billCodes={this.state.billCodes}
             formlist={this.state.formlist}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />}
diff --git a/src/templates/modalconfig/modalform/index.jsx b/src/templates/modalconfig/modalform/index.jsx
index c1e25a5..8c2d523 100644
--- a/src/templates/modalconfig/modalform/index.jsx
+++ b/src/templates/modalconfig/modalform/index.jsx
@@ -11,8 +11,7 @@
   static propTpyes = {
     dict: PropTypes.object, // 瀛楀吀椤�
     formlist: PropTypes.any,
-    card: PropTypes.object,
-    billCodes: PropTypes.array
+    card: PropTypes.object
   }
 
   state = {
@@ -23,7 +22,7 @@
 
   UNSAFE_componentWillMount () {
     let formlist = JSON.parse(JSON.stringify(this.props.formlist))
-    console.log(formlist)
+
     let type = formlist.filter(cell => cell.key === 'type')[0].initVal
     let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
     let _options = ['label', 'field', 'initval', 'type', 'readonly', 'required'] // 榛樿鏄剧ず椤�
@@ -45,9 +44,9 @@
     if (type === 'link') { // 鍏宠仈绫诲瀷銆佸鍔犲叧鑱斿瓧娈�
       _options = [..._options, 'linkField']
     }
-    console.log(type)
-    if (type === 'funcvar') {
-      _options = ['label', 'field', 'linkfield']
+
+    if (type === 'funcvar') { // 璁剧疆涓哄嚱鏁板彉閲忔椂锛屼笉闇�瑕佸叾浠栦俊鎭�
+      _options = ['label', 'field', 'type']
     }
     
     this.setState({
@@ -103,7 +102,7 @@
       }
 
       if (value === 'funcvar') {
-        _options = ['label', 'field', 'linkfield']
+        _options = ['label', 'field', 'type']
       }
       
       this.setState({
@@ -341,12 +340,10 @@
             }
           } else if ((values.type === 'multiselect' || values.type === 'select' || values.type === 'link') && values.resourceType === '1') {
             values.options = []
-          }
-
-          if (!values.type) {
-            values.type = 'funcvar'
+          } else if (values.type === 'funcvar') { // 鍑芥暟鍙橀噺涓哄彧璇诲厓绱�
             values.readonly = 'true'
           }
+
           if (isvalid) {
             resolve(values)
           } else {
diff --git a/src/templates/modalconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx
index 4a77626..2944e4d 100644
--- a/src/templates/modalconfig/settingform/index.jsx
+++ b/src/templates/modalconfig/settingform/index.jsx
@@ -154,6 +154,18 @@
               )}
             </Form.Item>
           </Col>
+          <Col span={12}>
+            <Form.Item label="鏄剧ず鏂瑰紡">
+              {getFieldDecorator('display', {
+                initialValue: config.setting.display || 'modal'
+              })(
+                <Radio.Group>
+                  <Radio value="modal">妯℃�佹</Radio>
+                  <Radio value="prompt">鏄惁妗�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
         </Row>
       </Form>
     )
diff --git a/src/templates/modalconfig/source.jsx b/src/templates/modalconfig/source.jsx
index 7f10db9..cc4a213 100644
--- a/src/templates/modalconfig/source.jsx
+++ b/src/templates/modalconfig/source.jsx
@@ -14,7 +14,8 @@
       container: 'tab',
       focus: '',
       finish: 'close',
-      clickouter: 'unclose'
+      clickouter: 'unclose',
+      display: 'modal'
     },
     tables: [],
     groups: [],
@@ -119,6 +120,12 @@
       label: '鏃堕棿妗嗭紙绉掞級',
       subType: 'datetime',
       url: ''
+    },
+    {
+      type: 'form',
+      label: '鍑芥暟鍙橀噺',
+      subType: 'funcvar',
+      url: ''
     }
   ]
 }
diff --git a/src/templates/modalviewconfig/actionform/index.jsx b/src/templates/modalviewconfig/actionform/index.jsx
new file mode 100644
index 0000000..cb6f923
--- /dev/null
+++ b/src/templates/modalviewconfig/actionform/index.jsx
@@ -0,0 +1,510 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, Icon, Radio, notification, Tooltip, InputNumber } from 'antd'
+import { btnIcons, btnClasses } from '@/utils/option.js'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+const { TextArea } = Input
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,  // 瀛楀吀椤�
+    formlist: PropTypes.any, // 琛ㄥ崟淇℃伅
+    card: PropTypes.any,     // 鎸夐挳淇℃伅
+    tabs: PropTypes.array    // 鎵�鏈夋爣绛鹃〉
+  }
+
+  state = {
+    formlist: null,  // 琛ㄥ崟淇℃伅
+    openType: null,  // 鎵撳紑鏂瑰紡
+    interType: null, // 鎺ュ彛绫诲瀷锛氬唴閮ㄣ�佸閮�
+    position: null,  // 鎸夐挳浣嶇疆
+    reqOptionSgl: [{
+      value: 'requiredSgl',
+      text: this.props.dict['header.form.requiredSgl']
+    }],
+    reqOptions: [{
+      value: 'notRequired',
+      text: this.props.dict['header.form.notRequired']
+    }, {
+      value: 'requiredSgl',
+      text: this.props.dict['header.form.requiredSgl']
+    }],
+    reqOptionsMutil: [{
+      value: 'notRequired',
+      text: this.props.dict['header.form.notRequired']
+    }, {
+      value: 'requiredSgl',
+      text: this.props.dict['header.form.requiredSgl']
+    }, {
+      value: 'required',
+      text: this.props.dict['header.form.required']
+    }, {
+      value: 'requiredOnce',
+      text: this.props.dict['header.form.requiredOnce']
+    }],
+    insertUpdateOptions: [{
+      value: '',
+      text: this.props.dict['header.form.empty']
+    }, {
+      value: 'insert',
+      text: this.props.dict['header.form.action.insert']
+    }, {
+      value: 'update',
+      text: this.props.dict['header.form.action.update']
+    }],
+    deleteOptions: [{
+      value: '',
+      text: this.props.dict['header.form.empty']
+    }, {
+      value: 'LogicDelete',
+      text: this.props.dict['header.form.action.LogicDelete']
+    }, {
+      value: 'delete',
+      text: this.props.dict['header.form.action.delete']
+    }]
+  }
+
+  
+  UNSAFE_componentWillMount () {
+    let _opentype = ''
+    let _intertype = ''
+    let _position = ''
+    let _tabType = ''
+    let _linkTab = ''
+    let _options = null
+
+    this.props.formlist.forEach(form => {
+      if (form.key === 'OpenType') {
+        _opentype = form.initVal
+      } else if (form.key === 'intertype') {
+        _intertype = form.initVal
+      } else if (form.key === 'position') {
+        _position = form.initVal
+      } else if (form.key === 'tabType') {
+        _tabType = form.initVal
+      } else if (form.key === 'linkTab') {
+        _linkTab = form.initVal
+      }
+    })
+
+    let _tabs = this.props.tabs.filter(tab => tab.type === _tabType)
+    let initTab = _tabs.filter(tab => tab.uuid === _linkTab)[0]
+
+    if (_opentype === 'innerpage') {                                     // 鏂伴〉闈紙鍐呴儴锛夛紝鍙�夋ā鏉�
+      _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
+    } else if (_opentype === 'outerpage') {                              // 鏂伴〉闈紙澶栭儴锛夛紝闇�瑕侀〉闈㈠湴鍧�
+      _options = ['label', 'Ot', 'OpenType', 'url', 'icon', 'class', 'position']
+    } else if (_opentype === 'blank' || _opentype === 'tab') {           // 鏂版爣绛炬垨褰撳墠椤甸潰鏇挎崲
+      _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position']
+    } else if (_opentype === 'popview') {                                // 妯℃�佹鏍囩椤�
+      _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
+    } else if (_opentype === 'excelIn' || _opentype === 'excelOut') {    // 瀵煎叆瀵煎嚭
+      if (_intertype === 'outer') {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
+      } else {
+        _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
+      }
+    } else {
+      if (_intertype === 'outer') {
+        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'method']
+      } else {
+        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
+      }
+    }
+    this.setState({
+      openType: _opentype,
+      interType: _intertype,
+      position: _position,
+      formlist: this.props.formlist.map(item => {
+        if (item.key === 'class') {
+          item.options = btnClasses
+        } else if (item.key === 'icon') {
+          item.options = btnIcons
+        } else if (item.key === 'Ot') {
+          if (_opentype === 'innerpage' || _position === 'grid') {
+            item.options = this.state.reqOptionSgl
+          } else if (['outerpage', 'blank', 'tab', 'popview'].includes(_opentype)) {
+            item.options = this.state.reqOptions
+          } else {
+            item.options = this.state.reqOptionsMutil
+          }
+        } else if (item.key === 'sqlType') {
+          if (['prompt', 'exec'].includes(_opentype)) {
+            item.options = this.state.deleteOptions
+          } else {
+            item.options = this.state.insertUpdateOptions
+          }
+        } else if (item.key === 'linkTab') {
+          item.options = [
+            {
+              value: '',
+              text: '鏂板缓'
+            },
+            ..._tabs
+          ]
+          if (!initTab) {
+            item.initVal = ''
+          }
+        }
+        item.hidden = !_options.includes(item.key)
+        return item
+      })
+    })
+  }
+
+  componentDidMount () {
+    const { card } = this.props
+
+    if (card.focus) {
+      try {
+        let _form = document.getElementById('label')
+        _form.select()
+      } catch {
+        console.warn('琛ㄥ崟focus澶辫触锛�')
+      }
+    }
+  }
+
+  // 鎵撳紑鏂瑰紡鎴栨樉绀轰綅缃彉鍖�
+  openTypeChange = (key, value) => {
+    if (key === 'OpenType') {
+      let _options = null
+      if (value === 'innerpage') {
+        _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
+      } else if (value === 'outerpage') {
+        _options = ['label', 'Ot', 'OpenType', 'url', 'icon', 'class', 'position']
+      } else if (value === 'blank' || value === 'tab') {
+        _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position']
+      } else if (value === 'popview') {
+        _options = ['label', 'Ot', 'OpenType', 'icon', 'class', 'position', 'tabType', 'linkTab', 'popClose']
+      } else if (value === 'excelIn' || value === 'excelOut') {
+        if (this.state.interType === 'outer') {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'icon', 'class', 'execSuccess', 'execError', 'method']
+        } else {
+          _options = ['label', 'OpenType', 'intertype', 'innerFunc', 'icon', 'class', 'execSuccess', 'execError']
+        }
+      } else {
+        if (this.state.interType === 'inner') {
+          _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
+        } else {
+          _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'interface', 'outerFunc', 'callbackFunc', 'method']
+        }
+      }
+      this.setState({
+        openType: value,
+        formlist: this.state.formlist.map(item => {
+          if (_options) {
+            item.hidden = !_options.includes(item.key)
+            if (item.key === 'intertype') {
+              item.initVal = this.state.interType
+            }
+          }
+          if (item.key === 'Ot') {
+            if (value === 'innerpage' || this.state.position === 'grid') {
+              item.options = this.state.reqOptionSgl
+              item.initVal = 'requiredSgl'
+            } else if (['outerpage', 'blank', 'tab', 'popview'].includes(value)) {
+              item.options = this.state.reqOptions
+              item.initVal = 'requiredSgl'
+            } else {
+              item.options = this.state.reqOptionsMutil
+            }
+            item.hidden = true
+          } else if (item.key === 'sqlType') {
+            if (['prompt', 'exec'].includes(value)) {
+              item.options = this.state.deleteOptions
+            } else {
+              item.options = this.state.insertUpdateOptions
+            }
+            item.initVal = ''
+            item.hidden = true
+          }
+          return item
+        })
+      }, () => {
+        if (['excelIn', 'excelOut'].includes(value)) return
+
+        this.setState({
+          formlist: this.state.formlist.map(item => {
+            if (item.key === 'Ot') {
+              item.hidden = false
+            } else if (item.key === 'sqlType' && ['prompt', 'exec', 'pop'].includes(value)) {
+              item.hidden = false
+            }
+            return item
+          })
+        })
+      })
+    } else if (key === 'position') {
+      this.setState({
+        position: value,
+        formlist: this.state.formlist.map(item => {
+          if (item.key === 'Ot') {
+            if (this.state.openType === 'innerpage' || value === 'grid') {
+              item.options = this.state.reqOptionSgl
+              item.initVal = 'requiredSgl'
+              item.hidden = true
+            } else if (['outerpage', 'blank', 'tab', 'popview'].includes(this.state.openType)) {
+              item.options = this.state.reqOptions
+              item.initVal = 'requiredSgl'
+              item.hidden = true
+            } else {
+              item.options = this.state.reqOptionsMutil
+            }
+          }
+          return item
+        })
+      }, () => {
+        this.setState({
+          formlist: this.state.formlist.map(item => {
+            if (item.key === 'Ot') {
+              item.hidden = false
+            }
+            return item
+          })
+        })
+      })
+    } else if (key === 'tabType') {
+      let _tabs = this.props.tabs.filter(tab => tab.type === value)
+
+      this.setState({
+        formlist: this.state.formlist.map(item => {
+          if (item.key === 'linkTab') {
+            item.options = [
+              {
+                value: '',
+                text: '鏂板缓'
+              },
+              ..._tabs
+            ]
+            item.initVal = ''
+            item.hidden = true
+          }
+          return item
+        })
+      }, () => {
+        this.setState({
+          formlist: this.state.formlist.map(item => {
+            if (item.key === 'linkTab') {
+              item.hidden = false
+            }
+            return item
+          })
+        })
+      })
+    }
+  }
+
+  onChange = (e, key) => {
+    let value = e.target.value
+    if (key === 'intertype') {
+      let _options = null
+      if (value === 'inner') {
+        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'sql', 'sqlType']
+      } else {
+        _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'Ot', 'icon', 'class', 'execSuccess', 'execError', 'interface', 'outerFunc', 'callbackFunc', 'method']
+      }
+      this.setState({
+        interType: value,
+        formlist: this.state.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+          return item
+        })
+      })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+
+    this.state.formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        let _rules = []
+        if (item.key === 'innerFunc') {
+          let str = '^(' + item.fields.join('|') + ')'
+          let _patten = new RegExp(str + '[0-9a-zA-Z_]*$', 'g')
+          _rules = [{
+            pattern: _patten,
+            message: '鍚嶇О鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶅拰涓嬪垝绾匡紝涓斾互鎸囧畾瀛楃寮�濮嬨��'
+          }, {
+            max: 50,
+            message: '鍐呴儴鍑芥暟鍚嶇О涓嶈秴杩�50涓瓧绗︺��'
+          }]
+        }
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: item.readonly ? false : !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  },
+                  ..._rules
+                ]
+              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'number') { // 鏂囨湰鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal
+              })(<InputNumber min={1} max={10000} precision={0} />)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.openTypeChange(item.key, value)}}
+                  getPopupContainer={() => document.getElementById('winter')}
+                >
+                  {item.options.map((option, index) =>
+                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
+                      {item.key === 'icon' && option.value && <Icon type={option.value} />} {option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'radio') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
+                  {
+                    item.options.map(option => {
+                      return (
+                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
+                      )
+                    })
+                  }
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'textarea') {
+        fields.push(
+          <Col span={24} key={index}>
+            <Form.Item label={item.label} className="textarea">
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal
+              })(<TextArea rows={4} />)}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          values.id = this.props.card.id
+          values.uuid = this.props.card.uuid
+          values.verify = this.props.card.verify || null
+
+          if (values.OpenType === 'excelIn' || values.OpenType === 'excelOut') {
+            values.position = 'toolbar'
+            values.Ot = 'notRequired'
+          } else if (values.OpenType === 'popview' && !values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d
+            values.linkTab = Utils.getuuid()
+          }
+
+          if (values.innerFunc === '' && values.sql === '') {
+            notification.warning({
+              top: 92,
+              message: this.props.dict['header.form.actionhelp.datasource'],
+              duration: 10
+            })
+          } else if (values.innerFunc === '' && values.sql !== '' && values.sqlType === '') {
+            notification.warning({
+              top: 92,
+              message: this.props.dict['header.form.actionhelp.sqlType'],
+              duration: 10
+            })
+          } else {
+            resolve({
+              type: 'action',
+              values
+            })
+          }
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 7 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 17 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form commontable-action-form" id="winter">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/actionform/index.scss b/src/templates/modalviewconfig/actionform/index.scss
new file mode 100644
index 0000000..c25cef2
--- /dev/null
+++ b/src/templates/modalviewconfig/actionform/index.scss
@@ -0,0 +1,33 @@
+.ant-advanced-search-form.commontable-action-form {
+  min-height: 190px;
+  .superconfig {
+    color: #1890ff;
+    cursor: pointer;
+  }
+  .textarea {
+    .ant-col-sm-7 {
+      width: 14%;
+    }
+    .ant-col-sm-17 {
+      width: 86%;
+    }
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+  .anticon-question-circle {
+    color: #c49f47;
+    position: relative;
+    left: -3px;
+  }
+  .with-button {
+    .ant-form-item-control-wrapper {
+      padding-right: 63px;
+    }
+    .ant-btn {
+      position: absolute;
+      right: 12px;
+      top: 4.5px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/index.jsx b/src/templates/modalviewconfig/index.jsx
new file mode 100644
index 0000000..cf9bfdc
--- /dev/null
+++ b/src/templates/modalviewconfig/index.jsx
@@ -0,0 +1,3132 @@
+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'
+import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty, Switch, Tooltip } from 'antd'
+import moment from 'moment'
+import ActionForm from './actionform'
+import SettingForm from './settingform'
+import TabForm from './tabform'
+import TabDragElement from './tabdragelement'
+import Api from '@/api'
+import SearchForm from '@/templates/tableshare/searchform'
+import ColumnForm from '@/templates/tableshare/columnform'
+import DragElement from '@/templates/tableshare/dragelement'
+import ColspanForm from '@/templates/tableshare/colspanform'
+import GridBtnForm from '@/templates/tableshare/gridbtnform'
+import EditCard from '@/templates/tableshare/editcard'
+import VerifyCard from '@/templates/tableshare/verifycard'
+import MenuForm from '@/templates/tableshare/menuform'
+import SourceElement from '@/templates/tableshare/dragelement/source'
+import zhCN from '@/locales/zh-CN/comtable.js'
+import enUS from '@/locales/en-US/comtable.js'
+import Utils from '@/utils/utils.js'
+import Source from './source'
+import './index.scss'
+
+const { Panel } = Collapse
+const { Option } = Select
+const { confirm } = Modal
+const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
+
+class ComTableConfig extends Component {
+  static propTpyes = {
+    type: PropTypes.string,
+    menu: PropTypes.any,
+    reloadmenu: PropTypes.func,
+    handleConfig: PropTypes.func,
+    handleSubConfig: PropTypes.func,
+    supMenuList: PropTypes.array
+  }
+
+  state = {
+    dict: CommonDict,        // 瀛楀吀
+    config: null,            // 椤甸潰閰嶇疆
+    visible: false,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪锛屾ā鎬佹鏄剧ず鎺у埗
+    modalTitle: '',          // 妯℃�佹鐨勬爣棰�
+    tableVisible: false,     // 鏁版嵁琛ㄥ瓧娈垫ā鎬佹
+    addType: '',             // 娣诲姞绫诲瀷-鎼滅储鏉′欢鎴栨樉绀哄垪
+    tableColumns: [],        // 琛ㄦ牸鏄剧ず鍒�
+    fields: null,            // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
+    menuformlist: null,      // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
+    formlist: null,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁
+    formtemp: '',            // 琛ㄥ崟绫诲瀷锛屾樉绀哄垪銆佹寜閽�佹悳绱㈡潯浠�
+    card: null,              // 缂栬緫鍏冪礌
+    searchloading: false,    // 鎼滅储鏉′欢鍔犺浇涓�
+    actionloading: false,    // 鎸夐挳鍔犺浇涓�
+    columnsloading: false,   // 鏄剧ず鍒楀姞杞戒腑
+    tabloading: false,       // 鏍囩椤靛姞杞戒腑
+    menuloading: false,      // 鑿滃崟淇濆瓨涓�
+    menucloseloading: false, // 鑿滃崟鍏抽棴鏃讹紝閫夋嫨淇濆瓨
+    loading: false,          // 鍔犺浇涓紝椤甸潰spin
+    settingVisible: false,   // 鍏ㄥ眬閰嶇疆妯℃�佹
+    closeVisible: false,     // 鍏抽棴妯℃�佹
+    tables: [],              // 鍙敤琛ㄥ悕
+    selectedTables: [],      // 宸查�夎〃鍚�
+    originMenu: null,        // 鍘熷鑿滃崟
+    originActions: null,     // 鍘熷鎸夐挳淇℃伅锛屼娇鐢ㄥ凡鏈夌敤鎴锋ā鏉�
+    delActions: [],          // 鍒犻櫎鎸夐挳鍒楄〃
+    funcLoading: false,      // 瀛樺偍杩囩▼鍒涘缓涓�
+    showColumnName: false,   // 鏄剧ず鍒楀瓧娈靛悕鎺у埗
+    tabviews: [],            // 鎵�鏈夋爣绛鹃〉
+    profileVisible: false    // 楠岃瘉淇℃伅妯℃�佹
+  }
+
+  /**
+   * @description 鏁版嵁棰勫鐞�
+   * 1銆佽缃〉闈㈤厤缃俊鎭紝鏂板缓鎴栨棤閰嶇疆淇℃伅鏃讹紙鍒囨崲妯℃澘鍚庢棤閰嶇疆淇℃伅锛夛紝浣跨敤妯℃澘榛樿閰嶇疆
+   * 2銆佽缃搷浣滅被鍨嬨�佸師濮嬭彍鍗曚俊鎭紙姣忔淇濆瓨鍚庨噸缃級銆佸凡浣跨敤琛ㄥ強鍩烘湰淇℃伅琛ㄥ崟
+   */
+  UNSAFE_componentWillMount () {
+    const { menu } = this.props
+
+    let _LongParam = menu.LongParam
+    let _config = ''
+
+    if (!_LongParam) {
+      _config = JSON.parse(JSON.stringify(Source.baseConfig))
+      if (!menu.isSubtable) { // 涓嶆槸閫夋嫨涓诲瓙琛ㄦ椂锛岄殣钘忔爣绛鹃〉
+        _config.tabs = []
+      }
+    } else {
+      _config = _LongParam
+    }
+    
+    let _oriActions = []
+    if (_config.type === 'user') {
+      _config.action = _config.action.map(item => {
+        let uuid = Utils.getuuid()
+
+        if (item.OpenType === 'pop') { // 鍚湁瀛愰厤缃」鐨勬寜閽�傘�傘��
+          _oriActions.push({
+            prebtn: JSON.parse(JSON.stringify(item)),
+            curuuid: uuid,
+            Template: 'Modal'
+          })
+        }
+
+        item.uuid = uuid
+
+        return item
+      })
+    }
+
+    _config.tabs = _config.tabs || []
+    _config.tabgroups = _config.tabgroups || ['tabs']
+    _config.setting.subtabs = _config.setting.subtabs || []
+
+    this.setState({
+      config: _config,
+      originActions: _oriActions,
+      originMenu: JSON.parse(JSON.stringify(menu)),
+      selectedTables: _config.tables || [],
+      menuformlist: [
+        {
+          type: 'select',
+          key: 'parentId',
+          label: this.state.dict['header.menu.supMenu'],
+          initVal: menu.ParentID,
+          required: true,
+          readonly: false,
+          options: this.props.supMenuList
+        },
+        {
+          type: 'text',
+          key: 'menuName',
+          label: this.state.dict['header.menu.menuName'],
+          initVal: menu.MenuName,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'menuNo',
+          label: this.state.dict['header.menu.menuNo'],
+          initVal: menu.MenuNo,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'opentype',
+          label: this.state.dict['header.menu.openType'],
+          initVal: menu.PageParam.OpenType,
+          required: true,
+          options: [{
+            MenuID: 'newtab',
+            text: this.state.dict['header.form.tab']
+          }, {
+            MenuID: 'newpage',
+            text: this.state.dict['header.form.newpage']
+          }, {
+            MenuID: 'currenttab',
+            text: this.state.dict['header.form.currenttab']
+          }]
+        }
+      ]
+    })
+  }
+
+  /**
+   * @description 鍔犺浇瀹屾垚鍚�
+   * 1銆佽幏鍙栫郴缁熷彲浣跨敤琛�
+   * 2銆佹牴鎹厤缃俊鎭腑宸蹭娇鐢ㄨ〃鑾峰彇鐩稿叧瀛楁淇℃伅
+   * 3銆佽幏鍙栨墍鏈夋爣绛鹃〉淇℃伅
+   */
+  componentDidMount () {
+    let param = {
+      func: 'sPC_Get_SelectedList',
+      LText: 'select TbName ,Remark from sDataDictionary where IsKey!=\'\' and Deleted =0',
+      obj_name: 'data',
+      arr_field: 'TbName,Remark'
+    }
+
+    param.LText = Utils.formatOptions(param.LText)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+    Api.getSystemConfig(param).then(res => {
+      if (res.status) {
+        this.setState({
+          tables: res.data
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+      }
+    })
+
+    let deffers = this.state.selectedTables.map(item => {
+      return new Promise(resolve => {
+        Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => {
+          res.TBName = item.TbName
+          resolve(res)
+        })
+      })
+    })
+    Promise.all(deffers).then(response => {
+      let _columns = []
+      response.forEach(res => {
+        if (res.status) {
+          let tabmsg = {
+            tableName: res.TBName,
+            columns: res.FDName.map(item => {
+              let _type = item.FieldType.toLowerCase()
+              let _decimal = 0
+              if (/^nvarchar/.test(_type)) {
+                _type = 'text'
+              } else if (/^int/.test(_type)) {
+                _type = 'number'
+              } else if (/^decimal/.test(_type)) {
+                _decimal = _type.split(',')[1]
+                _decimal = parseInt(_decimal)
+                if (_decimal > 4) {
+                  _decimal = 4
+                }
+                _type = 'number'
+              } else if (/^decimal/.test(_type)) {
+                _decimal = _type.split(',')[1]
+                _decimal = parseInt(_decimal)
+                if (_decimal > 4) {
+                  _decimal = 4
+                }
+                _type = 'number'
+              } else if (/^datetime/.test(_type)) {
+                _type = 'datetime'
+              } else if (/^date/.test(_type)) {
+                _type = 'date'
+              } else {
+                _type = 'text'
+              }
+  
+              return {
+                field: item.FieldName,
+                label: item.FieldDec,
+                type: _type,
+                datatype: _type,
+                decimal: _decimal
+              }
+            })
+          }
+          _columns.push(tabmsg)
+        } else {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+        }
+      })
+
+      this.setState({
+        tableColumns: _columns
+      })
+    })
+
+    Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
+      if (res.status) {
+        this.setState({
+          tabviews: res.UserTemp.map(temp => {
+            return {
+              uuid: temp.MenuID,
+              value: temp.MenuID,
+              text: temp.MenuName,
+              type: temp.Template,
+              MenuNo: temp.MenuNo
+            }
+          })
+        })
+      }
+    })
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = (state, callback) => {
+      return
+    }
+  }
+
+  handleList = (type, list, card) => {
+    const { config } = this.state
+
+    if (type === 'tabs') { // 鏍囩椤佃皟鏁撮『搴忔垨娣诲姞鍏冪礌
+      if (list.length > config[card.groupId].length) {
+        list = list.filter(item => !item.origin)
+  
+        this.setState({
+          tabloading: true,
+          config: {...config, [card.groupId]: list }
+        }, () => {
+          // 鍒锋柊瀵瑰簲鐨勯厤缃俊鎭�
+          this.setState({
+            tabloading: false
+          })
+          this.handleTab(card)
+        })
+      } else {
+        this.setState({config: {...config, [card.groupId]: list}})
+      }
+    } else {
+      if (list.length > config[type].length) {
+        list = list.filter(item => !item.origin)
+  
+        this.setState({
+          [type + 'loading']: true,
+          config: {...config, [type]: list }
+        }, () => {
+          // 鍒锋柊瀵瑰簲鐨勯厤缃俊鎭�
+          this.setState({
+            [type + 'loading']: false
+          })
+  
+          if (type === 'search') {
+            this.handleSearch(card)
+          } else if (type === 'action') {
+            this.handleAction(card)
+          } else if (type === 'columns') {
+            this.handleColumn(card)
+          } else if (type === 'tabs') {
+            this.handleTab(card)
+          }
+        })
+      } else {
+        this.setState({config: {...config, [type]: list}})
+      }
+    }
+  }
+
+  handleSearch = (card) => {
+    this.setState({
+      visible: true,
+      formtemp: 'search',
+      modalTitle: '缂栬緫-鎼滅储鏉′欢',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'field',
+          label: this.state.dict['header.form.field'],
+          initVal: card.field,
+          tooltip: '瀛楁鍚嶅彲浠ヤ娇鐢ㄩ�楀彿鍒嗛殧锛岃繘琛屽瀛楁缁煎悎鎼滅储锛屾敞锛氱患鍚堟悳绱粎鍦ㄦ枃鏈被鍨嬫椂鏈夋晥',
+          tooltipClass: 'middle',
+          required: true,
+          rules: [{
+            pattern: /^[\u4E00-\u9FA50-9a-zA-Z,_]*$/ig,
+            message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯'
+          }, {
+            max: 50,
+            message: '瀛楁鍚嶆渶澶�50涓瓧绗︼紒'
+          }],
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'type',
+          label: this.state.dict['header.form.type'],
+          initVal: card.type,
+          required: true,
+          options: [{
+            value: 'text',
+            text: this.state.dict['header.form.text']
+          }, {
+            value: 'select',
+            text: this.state.dict['header.form.select']
+          }, {
+            value: 'multiselect',
+            text: this.state.dict['header.form.multiselect']
+          }, {
+            value: 'link',
+            text: this.state.dict['header.form.link']
+          }, {
+            value: 'date',
+            text: this.state.dict['header.form.dateday']
+          }, {
+            value: 'dateweek',
+            text: this.state.dict['header.form.dateweek']
+          }, {
+            value: 'datemonth',
+            text: this.state.dict['header.form.datemonth']
+          }, {
+            value: 'daterange',
+            text: this.state.dict['header.form.daterange']
+          }]
+        },
+        {
+          type: 'text',
+          key: 'initval',
+          label: this.state.dict['header.form.initval'],
+          initVal: card.initval,
+          required: false
+        },
+        {
+          type: 'radio',
+          key: 'resourceType',
+          label: this.state.dict['header.form.resourceType'],
+          initVal: card.resourceType || '0',
+          required: true,
+          options: [{
+            value: '0',
+            text: this.state.dict['header.form.custom']
+          }, {
+            value: '1',
+            text: this.state.dict['header.form.datasource']
+          }]
+        },
+        {
+          type: 'radio',
+          key: 'setAll',
+          label: this.state.dict['header.form.setAll'],
+          initVal: card.setAll || 'false',
+          options: [{
+            value: 'true',
+            text: this.state.dict['header.form.true']
+          }, {
+            value: 'false',
+            text: this.state.dict['header.form.false']
+          }]
+        },
+        {
+          type: 'textarea',
+          key: 'dataSource',
+          label: this.state.dict['header.form.datasource'],
+          initVal: card.dataSource || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'options',
+          key: 'options',
+          label: '',
+          initVal: card.options || [],
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'linkField',
+          label: this.state.dict['header.form.linkField'],
+          initVal: card.linkField || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'valueField',
+          label: this.state.dict['header.form.valueField'],
+          initVal: card.valueField || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'valueText',
+          label: this.state.dict['header.form.valueText'],
+          initVal: card.valueText || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'orderBy',
+          label: this.state.dict['header.form.orderBy'],
+          initVal: card.orderBy || '',
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'orderType',
+          label: this.state.dict['header.form.orderType'],
+          initVal: card.orderType || 'asc',
+          options: [{
+            value: 'asc',
+            text: this.state.dict['header.form.asc']
+          }, {
+            value: 'desc',
+            text: this.state.dict['header.form.desc']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'match',
+          label: this.state.dict['header.form.match'],
+          initVal: card.match || 'like',
+          required: true,
+          options: [{
+            value: 'like',
+            text: 'like'
+          }, {
+            value: 'equal',
+            text: 'equal'
+          }, {
+            value: 'greater',
+            text: '>'
+          }, {
+            value: 'less',
+            text: '<'
+          }, {
+            value: 'greaterequal',
+            text: '>='
+          }]
+        },
+        {
+          type: 'select',
+          key: 'display',
+          label: this.state.dict['header.form.display'],
+          initVal: card.display || 'dropdown',
+          required: true,
+          options: [{
+            value: 'dropdown',
+            text: this.state.dict['header.form.dropdown']
+          }, {
+            value: 'button',
+            text: this.state.dict['header.form.button']
+          }]
+        }
+      ]
+    })
+  }
+
+  handleAction = (card, type) => {
+    let ableField = this.props.permFuncField.join(', ')
+    this.setState({
+      visible: true,
+      formtemp: 'action',
+      modalTitle: type === 'copy' ? '澶嶅埗-鎸夐挳' : '缂栬緫-鎸夐挳',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'OpenType',
+          label: this.state.dict['header.form.openType'],
+          initVal: card.OpenType,
+          required: true,
+          options: [{
+            value: 'pop',
+            text: this.state.dict['header.form.popform']
+          }, {
+            value: 'prompt',
+            text: this.state.dict['header.form.prompt']
+          }, {
+            value: 'exec',
+            text: this.state.dict['header.form.exec']
+          }, {
+            value: 'excelIn',
+            text: this.state.dict['header.form.excelIn']
+          }, {
+            value: 'excelOut',
+            text: this.state.dict['header.form.excelOut']
+          }, {
+            value: 'popview',
+            text: this.state.dict['header.form.popview']
+          }, {
+            value: 'tab',
+            text: this.state.dict['header.form.tab']
+          }, {
+            value: 'blank',
+            text: this.state.dict['header.form.blank']
+          }, {
+            value: 'innerpage',
+            text: this.state.dict['header.form.newpage.inner']
+          }, {
+            value: 'outerpage',
+            text: this.state.dict['header.form.newpage.outer']
+          }]
+        }, {
+          type: 'select',
+          key: 'tabType',
+          label: this.state.dict['header.form.tabType'],
+          initVal: card.tabType || 'SubTable',
+          required: true,
+          options: [{
+            value: 'SubTable',
+            text: this.state.dict['header.menu.tab.subtable']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'linkTab',
+          label: '鍏宠仈鏍囩',
+          initVal: card.linkTab || '',
+          required: false,
+          options: []
+        },
+        {
+          type: 'select',
+          key: 'pageTemplate',
+          label: this.state.dict['header.form.pageTemplate'],
+          initVal: card.pageTemplate,
+          required: true,
+          options: []
+        },
+        {
+          type: 'text',
+          key: 'url',
+          label: this.state.dict['header.form.newpage.url'],
+          initVal: card.url || '',
+          required: true
+        },
+        {
+          type: 'radio',
+          key: 'intertype',
+          label: this.state.dict['header.form.intertype'],
+          initVal: card.intertype || 'inner',
+          required: true,
+          options: [{
+            value: 'inner',
+            text: this.state.dict['header.form.interface.inner']
+          }, {
+            value: 'outer',
+            text: this.state.dict['header.form.interface.outer']
+          }]
+        },
+        {
+          type: 'text',
+          key: 'innerFunc',
+          label: this.state.dict['header.form.innerFunc'],
+          initVal: card.innerFunc,
+          tooltip: <div>
+            <p>鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField}绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;</p>
+            <p>澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�</p>
+          </div>,
+          fields: this.props.permFuncField,
+          tooltipClass: 'middle',
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'interface',
+          label: this.state.dict['header.form.interface'],
+          initVal: card.interface,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'outerFunc',
+          label: this.state.dict['header.form.outerFunc'],
+          initVal: card.outerFunc,
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'callbackFunc',
+          label: this.state.dict['header.form.callbackFunc'],
+          initVal: card.callbackFunc,
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'position',
+          label: this.state.dict['header.form.position'],
+          initVal: card.position || 'toolbar',
+          required: true,
+          options: [{
+            value: 'toolbar',
+            text: this.state.dict['header.form.toolbar']
+          }, {
+            value: 'grid',
+            text: this.state.dict['header.form.grid']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'Ot',
+          label: this.state.dict['header.form.isRequired'],
+          initVal: card.Ot || 'requiredSgl',
+          required: true,
+          options: []
+        },
+        {
+          type: 'select',
+          key: 'execSuccess',
+          label: this.state.dict['header.form.execSuccess'],
+          initVal: card.execSuccess || 'never',
+          required: true,
+          options: [{
+            value: 'never',
+            text: this.state.dict['header.form.refresh.never']
+          }, {
+            value: 'grid',
+            text: this.state.dict['header.form.refresh.grid']
+          }, {
+            value: 'view',
+            text: this.state.dict['header.form.refresh.view']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'execError',
+          label: this.state.dict['header.form.execError'],
+          initVal: card.execError || 'never',
+          required: true,
+          options: [{
+            value: 'never',
+            text: this.state.dict['header.form.refresh.never']
+          }, {
+            value: 'grid',
+            text: this.state.dict['header.form.refresh.grid']
+          }, {
+            value: 'view',
+            text: this.state.dict['header.form.refresh.view']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'popClose',
+          label: this.state.dict['header.form.popClose'],
+          initVal: card.popClose || 'never',
+          required: true,
+          options: [{
+            value: 'never',
+            text: this.state.dict['header.form.refresh.never']
+          }, {
+            value: 'grid',
+            text: this.state.dict['header.form.refresh.grid']
+          }, {
+            value: 'view',
+            text: this.state.dict['header.form.refresh.view']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'icon',
+          label: this.state.dict['header.form.icon'],
+          initVal: card.icon,
+          required: false,
+          options: []
+        },
+        {
+          type: 'select',
+          key: 'class',
+          label: this.state.dict['header.form.class'],
+          initVal: card.class,
+          required: false,
+          options: []
+        },
+        {
+          type: 'text',
+          key: 'sql',
+          label: this.state.dict['header.form.datasource'],
+          initVal: card.sql || this.state.config.setting.tableName || '',
+          tooltip: this.state.dict['header.form.actionhelp.datasource'],
+          required: false
+        },
+        {
+          type: 'select',
+          key: 'sqlType',
+          label: this.state.dict['header.form.action.type'],
+          initVal: card.sqlType || '',
+          tooltip: this.state.dict['header.form.actionhelp.sqlType'],
+          required: false,
+          options: []
+        }
+      ]
+    })
+  }
+
+  handleColumn = (card) => {
+    if (card.type !== 'colspan') {
+      this.setState({
+        visible: true,
+        formtemp: 'columns',
+        modalTitle: '缂栬緫-鏄剧ず鍒�',
+        card: card,
+        formlist: [
+          {
+            type: 'text',
+            key: 'label',
+            label: this.state.dict['header.form.name'],
+            initVal: card.label,
+            required: true
+          },
+          {
+            type: 'text',
+            key: 'field',
+            label: this.state.dict['header.form.field'],
+            initVal: card.field,
+            required: true,
+            rules: [{
+              pattern: /^[\u4E00-\u9FA50-9a-zA-Z_]*$/ig,
+              message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶃�佹眽瀛椾互鍙奯'
+            }, {
+              max: 50,
+              message: '瀛楁鍚嶆渶澶�50涓瓧绗︼紒'
+            }],
+            readonly: false
+          },
+          {
+            type: 'select',
+            key: 'type',
+            label: this.state.dict['header.form.type'],
+            initVal: card.type,
+            required: true,
+            options: [{
+              value: 'text',
+              text: this.state.dict['header.form.text']
+            }, {
+              value: 'number',
+              text: this.state.dict['header.form.number']
+            }, {
+              value: 'picture',
+              text: this.state.dict['header.form.picture']
+            }, {
+              value: 'textarea',
+              text: this.state.dict['header.form.textarea']
+            }]
+          },
+          {
+            type: 'select',
+            key: 'Align',
+            label: this.state.dict['header.form.align'],
+            initVal: card.Align,
+            required: true,
+            options: [{
+              value: 'left',
+              text: this.state.dict['header.form.alignLeft']
+            }, {
+              value: 'right',
+              text: this.state.dict['header.form.alignRight']
+            }, {
+              value: 'center',
+              text: this.state.dict['header.form.alignCenter']
+            }]
+          },
+          {
+            type: 'radio',
+            key: 'Hide',
+            label: this.state.dict['header.form.Hide'],
+            initVal: card.Hide,
+            required: true,
+            options: [{
+              value: 'true',
+              text: this.state.dict['header.form.true']
+            }, {
+              value: 'false',
+              text: this.state.dict['header.form.false']
+            }]
+          },
+          {
+            type: 'radio',
+            key: 'IsSort',
+            label: this.state.dict['header.form.IsSort'],
+            initVal: card.IsSort,
+            required: true,
+            options: [{
+              value: 'true',
+              text: this.state.dict['header.form.true']
+            }, {
+              value: 'false',
+              text: this.state.dict['header.form.false']
+            }]
+          },
+          {
+            type: 'number',
+            key: 'Width',
+            min: 1,
+            max: 1000,
+            decimal: 0,
+            label: this.state.dict['header.form.columnWidth'],
+            initVal: card.Width,
+            required: true
+          },
+          {
+            type: 'number',
+            key: 'decimal',
+            min: 0,
+            max: 18,
+            decimal: 0,
+            label: this.state.dict['header.form.decimal'],
+            initVal: card.decimal,
+            required: false
+          },
+          {
+            type: 'select',
+            key: 'format',
+            label: this.state.dict['header.form.format'],
+            initVal: card.format || '',
+            options: [{
+              value: '',
+              text: this.state.dict['header.form.empty']
+            }, {
+              value: 'thdSeparator',
+              text: this.state.dict['header.form.thdSeparator']
+            }],
+            required: false
+          },
+          {
+            type: 'text',
+            key: 'prefix',
+            label: this.state.dict['header.form.prefix'],
+            initVal: card.prefix || '',
+            required: false,
+            readonly: false
+          },
+          {
+            type: 'text',
+            key: 'postfix',
+            label: this.state.dict['header.form.postfix'],
+            initVal: card.postfix || '',
+            // tooltip: '鍚庣紑鍊艰缃负"\\n",琛ㄧず鎹㈣',
+            tooltipClass: 'middle',
+            required: false,
+            readonly: false
+          },
+          {
+            type: 'select',
+            key: 'match',
+            label: this.state.dict['header.form.match'],
+            initVal: card.match || '',
+            options: [{
+              value: '',
+              text: this.state.dict['header.form.empty']
+            }, {
+              value: '>',
+              text: '>'
+            }, {
+              value: '<',
+              text: '<'
+            }, {
+              value: '>=',
+              text: '>='
+            }, {
+              value: '<=',
+              text: '<='
+            }],
+            required: false
+          },
+          {
+            type: 'text',
+            key: 'matchVal',
+            min: -Infinity,
+            max: Infinity,
+            decimal: 0,
+            label: this.state.dict['header.form.matchVal'],
+            initVal: card.matchVal || '',
+            required: false,
+            readonly: false
+          },
+          {
+            type: 'select',
+            key: 'color',
+            label: this.state.dict['header.form.color'],
+            initVal: card.color || '',
+            options: [{
+              value: '',
+              text: this.state.dict['header.form.empty']
+            }, {
+              value: 'red',
+              text: '绾㈣壊锛堝唴瀹癸級'
+            }, {
+              value: 'redbg',
+              text: '绾㈣壊锛堣儗鏅級'
+            }, {
+              value: 'orange',
+              text: '姗欒壊锛堝唴瀹癸級'
+            }, {
+              value: 'orangebg',
+              text: '姗欒壊锛堣儗鏅級'
+            }, {
+              value: 'green',
+              text: '缁胯壊锛堝唴瀹癸級'
+            }, {
+              value: 'greenbg',
+              text: '缁胯壊锛堣儗鏅級'
+            }],
+            required: false
+          }
+        ]
+      })
+    } else {
+      this.setState({
+        visible: true,
+        formtemp: 'columns',
+        modalTitle: '缂栬緫-鍚堝苟鍒�',
+        card: card
+      })
+    }
+  }
+
+  handleTab = (card) => {
+    const { config } = this.state
+
+    let index = 0 // 绛涢�変笅涓�缁�
+    config.tabgroups.forEach((groupId, i) => {
+      if (groupId === card.groupId) {
+        index = i
+      }
+    })
+
+    let menus = []
+    let subtabs = card.subtabs || []
+    let nextTabId = config.tabgroups[index + 1]
+
+    if (nextTabId) {
+      let _tabMap = new Map()
+      let _usedTabMap = new Map()
+
+      config[nextTabId].forEach(tab => { // 涓嬬骇鎵�鏈夌殑鏍囩
+        menus.push(tab)
+        _tabMap.set(tab.uuid, true)
+      })
+
+      config[card.groupId].forEach(tab => { // 鍚岀骇鏍囩宸查�夌殑涓嬬骇鏍囩
+        if (tab.uuid === card.uuid) return
+
+        tab.subtabs.forEach(subtab => {
+          _usedTabMap.set(subtab, true)
+        })
+      })
+
+      config.setting.subtabs.forEach(subtab => { // 涓昏〃宸查�夌殑涓嬬骇鏍囩
+        _usedTabMap.set(subtab, true)
+      })
+
+      subtabs = subtabs.filter(tab => _tabMap.has(tab.uuid) && !_usedTabMap.has(tab.uuid))
+      menus = menus.filter(tab => !_usedTabMap.has(tab.uuid))
+    } else {
+      subtabs = []
+    }
+
+    this.setState({
+      visible: true,
+      formtemp: 'tabs',
+      modalTitle: '缂栬緫-鏍囩椤�',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label || '',
+          required: true
+        },
+        {
+          type: 'select',
+          key: 'type',
+          label: this.state.dict['header.form.tabType'],
+          initVal: card.type || 'SubTable',
+          required: true,
+          options: [{
+            value: 'SubTable',
+            text: this.state.dict['header.menu.tab.subtable']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'linkTab',
+          label: '鍏宠仈鏍囩',
+          initVal: card.linkTab || '',
+          required: false,
+          options: []
+        },
+        {
+          type: 'select',
+          key: 'icon',
+          label: this.state.dict['header.menu.icon'],
+          initVal: card.icon || '',
+          required: false,
+          options: [{
+            value: '',
+            text: this.state.dict['header.form.empty']
+          }, {
+            value: 'table',
+            text: 'table'
+          }, {
+            value: 'bar-chart',
+            text: 'bar-chart'
+          }, {
+            value: 'pie-chart',
+            text: 'pie-chart'
+          }, {
+            value: 'line-chart',
+            text: 'line-chart'
+          }]
+        },
+        {
+          type: 'mutilselect',
+          key: 'subtabs',
+          label: '涓嬬骇鏍囩',
+          initVal: subtabs,
+          required: false,
+          options: menus
+        }
+      ]
+    })
+  }
+
+  handleGridBtn = () => {
+    this.setState({
+      visible: true,
+      formtemp: 'gridbtn',
+      modalTitle: '缂栬緫-鎿嶄綔鍒�',
+    })
+  }
+
+  /**
+   * @description 鎼滅储銆佹寜閽�佹樉绀哄垪淇敼鍚庢彁浜や繚瀛�
+   * 1銆佹悳绱㈡潯浠朵繚瀛橈紝褰撶被鍨嬩负涓嬫媺妗嗕笖瀛樺湪鏁版嵁婧愭椂锛屽皢鏌ヨ鏉′欢鎷兼帴涓簊ql锛屽苟鐢╞ase64杞爜
+   * 2銆佹寜閽寘鎷甯哥紪杈戝拰澶嶅埗锛屽鍒舵椂,鎸夐挳鍒楁湯灏炬坊鍔�
+   * 3銆佹坊鍔犳垨缂栬緫鍒楋紝淇濆瓨鏃讹紝濡傛寜閽綅缃缃负琛ㄦ牸锛屽垯淇敼鎿嶄綔鍒楁樉绀虹姸鎬�
+   */
+  handleSubmit = () => {
+    const { menu } = this.props
+    const { card } = this.state
+    let _config = JSON.parse(JSON.stringify(this.state.config))
+
+    if (this.state.formtemp !== 'gridbtn') {
+      this.formRef.handleConfirm().then(res => {
+        let isupdate = false
+
+        if (res.type === 'action' && card.originCard && res.values.OpenType === 'pop') {
+          Api.getSystemConfig({
+            func: 'sPC_Get_LongParam',
+            MenuID: card.originCard.uuid
+          }).then(result => {
+            if (result.status && result.LongParam) {
+              let param = {
+                func: 'sPC_ButtonParam_AddUpt',
+                ParentID: menu.MenuID,
+                MenuID: res.values.uuid,
+                MenuNo: menu.MenuNo,
+                Template: 'Modal',
+                MenuName: res.values.label,
+                PageParam: JSON.stringify({Template: 'Modal'}),
+                LongParam: result.LongParam
+              }
+              Api.getSystemConfig(param).then(response => {
+                if (!response.status) {
+                  notification.warning({
+                    top: 92,
+                    message: response.message,
+                    duration: 10
+                  })
+                }
+              })
+            }
+          })
+        }
+  
+        if (res.type !== 'tabs') {
+          _config[res.type] = _config[res.type].map(item => {
+            if (item.uuid === res.values.uuid) {
+              isupdate = true
+              return res.values
+            } else {
+              return item
+            }
+          })
+          _config[res.type] = _config[res.type].filter(item => !item.origin)
+    
+          if (!isupdate) { // 鎿嶄綔涓嶆槸淇敼锛屾坊鍔犲厓绱犺嚦鍒楄〃
+            _config[res.type].push(res.values)
+          }
+        } else { // 鏍囩椤电殑娣诲姞涓庝慨鏀�
+          _config[res.values.groupId] = _config[res.values.groupId].map(item => {
+            if (item.uuid === res.values.uuid) {
+              isupdate = true
+              return res.values
+            } else {
+              return item
+            }
+          })
+          _config[res.values.groupId] = _config[res.values.groupId].filter(item => !item.origin)
+    
+          if (!isupdate) { // 鎿嶄綔涓嶆槸淇敼锛屾坊鍔犲厓绱犺嚦鍒楄〃
+            _config[res.values.groupId].push(res.values)
+          }
+        }
+        
+  
+        if (res.type === 'action') {
+          let gridbtn = _config.action.filter(act => act.position === 'grid')
+          let _display = false
+  
+          if (gridbtn.length > 0) {
+            _display = true
+          }
+  
+          if (_config.gridBtn) {
+            _config.gridBtn.display = _display
+          } else {
+            _config.gridBtn = {
+              display: _display,
+              Align: 'center',
+              IsSort: 'false',
+              uuid: Utils.getuuid(),
+              label: this.state.dict['header.form.column.action'],
+              type: 'action',
+              style: 'button',
+              show: 'horizontal',
+              Width: 120
+            }
+          }
+        }
+
+        this.setState({
+          config: _config,
+          searchloading: true,
+          actionloading: true,
+          columnsloading: true,
+          tabloading: true,
+          visible: false
+        }, () => {
+          this.setState({
+            searchloading: false,
+            actionloading: false,
+            columnsloading: false,
+            tabloading: false
+          })
+        })
+      })
+    } else {
+      this.formRef.handleConfirm().then(res => {
+        _config.gridBtn = res
+
+        this.setState({
+          config: _config,
+          visible: false
+        })
+      })
+    }
+  }
+
+  /**
+   * @description 鍒涘缓鎸夐挳瀛樺偍杩囩▼
+   */
+  creatFunc = () => {
+    const { menu } = this.props
+    let _config = JSON.parse(JSON.stringify(this.state.config))
+
+    this.formRef.handleConfirm().then(res => {
+      let btn = res.values  // 鎸夐挳淇℃伅
+      let newLText = ''     // 鍒涘缓瀛樺偍杩囩▼sql
+      let DelText = ''      // 鍒犻櫎瀛樺偍杩囩▼sql
+      let isExit = false    // 瀛樺偍杩囩▼鏄惁瀛樺湪
+      let sysTVPText = ''   // 宸叉湁鐨勫瓨鍌ㄨ繃绋嬭鍙�(浜戠)
+      let localTVPText = '' // 宸叉湁鐨勫瓨鍌ㄨ繃绋嬭鍙�(鏈湴)
+
+      // 鍒涘缓瀛樺偍杩囩▼锛屽繀椤诲~鍐欏唴閮ㄥ嚱鏁板悕
+      if (!btn.innerFunc) {
+        notification.warning({
+          top: 92,
+          message: '璇峰~鍐欏唴閮ㄥ嚱鏁帮紒',
+          duration: 10
+        })
+        return
+      }
+
+      // 鍒涘缓涓�
+      this.setState({
+        funcLoading: true
+      })
+
+      new Promise(resolve => {
+        // 寮圭獥锛堣〃鍗曪級绫绘寜閽紝鍏堣幏鍙栨寜閽厤缃俊鎭紝濡傛灉灏氭湭閰嶇疆鎸夐挳鍒欎細鎶ラ敊骞剁粓姝€��
+        // 鑾峰彇淇℃伅鍚庣敓鎴愬垹闄ゅ拰鍒涘缓瀛樺偍杩囩▼鐨勮鍙�
+        if (btn.OpenType === 'pop') {
+          Api.getSystemConfig({
+            func: 'sPC_Get_LongParam',
+            MenuID: btn.uuid
+          }).then(res => {
+            let _LongParam = ''
+            if (res.status && res.LongParam) {
+              _LongParam = window.decodeURIComponent(window.atob(res.LongParam))
+              try {
+                _LongParam = JSON.parse(_LongParam)
+              } catch (e) {
+                _LongParam = ''
+              }
+            }
+
+            if (_LongParam) {
+              let fields = []
+              if (_LongParam.groups.length > 0) {
+                _LongParam.groups.forEach(group => {
+                  fields = [...fields, ...group.sublist]
+                })
+              } else {
+                fields = _LongParam.fields
+              }
+
+              let _param = {
+                funcName: btn.innerFunc,
+                name: _config.setting.tableName || '',
+                fields: fields,
+                menuNo: menu.MenuNo
+              }
+              newLText = Utils.formatOptions(Utils.getfunc(_param, btn, menu, _config))
+              DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName))
+              resolve(true)
+            } else {
+              resolve(false)
+              notification.warning({
+                top: 92,
+                message: '寮圭獥锛堣〃鍗曪級鎸夐挳锛岃鍏堥厤缃〃鍗曚俊鎭紒',
+                duration: 10
+              })
+            }
+          })
+        } else {
+          let _param = {
+            funcName: btn.innerFunc,
+            name: _config.setting.tableName || '',
+            fields: '',
+            menuNo: menu.MenuNo
+          }
+          newLText = Utils.formatOptions(Utils.getfunc(_param, btn, menu, _config))
+          DelText = Utils.formatOptions(Utils.dropfunc(_param.funcName))
+          resolve(true)
+        }
+      }).then(res => {
+        // 鑾峰彇浜戠鍙婃湰鍦帮紝鏄惁宸插瓨鍦ㄨ瀛樺偍杩囩▼鐨勪俊鎭�
+        if (res === false) return res
+
+        let sysDefer = new Promise(resolve => {
+          Api.getSystemConfig({
+            func: 'sPC_Get_TVP', // 浜戠鑾峰彇瀛樺偍缁撴灉
+            TVPName: btn.innerFunc
+          }).then(result => {
+            resolve(result)
+          })
+        })
+
+        let localDefer = new Promise(resolve => {
+          let _param = { // 鑾峰彇鏈湴瀛樺偍杩囩▼淇℃伅
+            func: 's_get_userproc',
+            LText: btn.innerFunc
+          }
+          _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+          _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+          
+          Api.getLocalConfig(_param).then(result => {
+            resolve(result)
+          })
+        })
+        
+        return Promise.all([sysDefer, localDefer])
+      }).then(res => {
+        // 浜戠缁撴灉涓庢柊璇彞涓嶅悓鏃讹紝鏇存柊浜戠淇℃伅
+        if (res === false) return res
+
+        let isError = false
+
+        res.forEach((result, index) => {
+          if (!result.status) {
+            notification.warning({
+              top: 92,
+              message: result.message,
+              duration: 10
+            })
+            isError = true
+          } else if (index === 0) {
+            sysTVPText = result.TVPText
+          } else {
+            if (result.Ltext) { // 鏈湴瀛樺偍杩囩▼鏄惁瀛樺湪
+              isExit = true
+            }
+            localTVPText = Utils.formatOptions(result.Ltext)
+          }
+        })
+
+        if (isError) return false
+        
+        if ((newLText === localTVPText) && (newLText === sysTVPText)) {
+          return 'drop'
+        } else if (!localTVPText || (localTVPText === sysTVPText)) {
+          // 鏈湴瀛樺偍杩囩▼涓嶅瓨鍦紝灏嗘柊鐨勫瓨鍌ㄨ繃绋嬫洿鏂拌嚦浜戠
+          return Api.getSystemConfig({
+            func: 'sPC_TVP_InUp',
+            TVPName: btn.innerFunc,
+            TVPText: newLText,
+            TypeName: 'P'
+          })
+        } else {
+          return new Promise(resolve => {
+            Api.getSystemConfig({ // 娣诲姞鐜版湁鐨勬湰鍦板瓨鍌ㄨ繃绋嬭嚦浜戠
+              func: 'sPC_TVP_InUp',
+              TVPName: btn.innerFunc,
+              TVPText: localTVPText,
+              TypeName: 'P'
+            }).then(result => {
+              if (result.status) {
+                Api.getSystemConfig({
+                  func: 'sPC_TVP_InUp', // 娣诲姞鏈�鏂扮殑瀛樺偍杩囩▼鑷充簯绔�
+                  TVPName: btn.innerFunc,
+                  TVPText: newLText,
+                  TypeName: 'P'
+                }).then(response => {
+                  resolve(response)
+                })
+              } else {
+                resolve(result)
+              }
+            })
+          })
+        }
+      }).then(res => {
+        // 浜戠淇℃伅鏇存柊鍚庯紝鍒ゆ柇鏄垹闄ゆ垨鏄洿鎺ユ柊寤哄瓨鍌ㄨ繃绋�
+        if (res === false || res === 'drop') return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else if (isExit) {
+          return 'drop'
+        } else {
+          return 'create'
+        }
+      }).then(res => {
+        // 鍒犻櫎瀛樺偍杩囩▼
+        if (res === false || res === 'create') return res
+
+        let _param = {
+          func: 'sPC_TableData_InUpDe',
+          LText: DelText,
+          TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋�
+        }
+
+        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+
+        return Api.getLocalConfig(_param)
+      }).then(res => {
+        // 鏍规嵁涓婅堪鎿嶄綔缁撴灉锛屽垽鏂槸鍚︽柊寤哄瓨鍌ㄨ繃绋�
+        if (res === false || res === 'create') return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else {
+          return 'create'
+        }
+      }).then(res => {
+        // 鏂板缓瀛樺偍杩囩▼
+        if (res === false) return res
+
+        let _param = {
+          func: 'sPC_TableData_InUpDe',
+          LText: newLText,
+          TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋�
+        }
+        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+
+        return Api.getLocalConfig(_param)
+      }).then(res => {
+        // 澶勭悊鏂板缓缁撴灉
+        if (res === false) return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else {
+          notification.success({
+            top: 92,
+            message: '鍒涘缓鎴愬姛',
+            duration: 2
+          })
+          return true
+        }
+      }).then(res => {
+        // 鏂板缓鎴愬姛鍚庯紝鏇存柊椤甸潰鎸夐挳淇℃伅
+        if (res === false) {
+          this.setState({
+            funcLoading: false
+          })
+          return
+        }
+
+        let isupdate = false
+        _config.action = _config.action.map(item => {
+          if (item.uuid === btn.uuid) {
+            isupdate = true
+            return btn
+          } else {
+            return item
+          }
+        })
+        _config.action = _config.action.filter(item => !item.origin)
+
+
+        if (!isupdate) { // 鎿嶄綔涓嶆槸淇敼锛屾坊鍔犲厓绱犺嚦鍒楄〃
+          _config.action.push(btn)
+        }
+
+        let gridbtn = _config.action.filter(act => act.position === 'grid')
+        let _display = false
+
+        if (gridbtn.length > 0) {
+          _display = true
+        }
+
+        if (_config.gridBtn) {
+          _config.gridBtn.display = _display
+        } else {
+          _config.gridBtn = {
+            display: _display,
+            Align: 'center',
+            IsSort: 'false',
+            uuid: Utils.getuuid(),
+            label: this.state.dict['header.form.column.action'],
+            type: 'action',
+            style: 'button',
+            show: 'horizontal',
+            Width: 120
+          }
+        }
+
+        this.setState({
+          config: _config,
+          actionloading: true,
+          funcLoading: false
+        }, () => {
+          this.setState({
+            actionloading: false
+          })
+        })
+      })
+    })
+  }
+
+  /**
+   * @description 鍒涘缓琛ㄦ牸瀛樺偍杩囩▼
+   */
+  tableCreatFunc = () => {
+    const { menu } = this.props
+    let config = JSON.parse(JSON.stringify(this.state.config))
+
+    this.settingRef.handleConfirm().then(res => {
+      const setting = res
+      if (!(setting.interType === 'inner') || !setting.innerFunc) {
+        notification.warning({
+          top: 92,
+          message: '鎺ュ彛绫诲瀷涓�-鍐呴儴锛屼笖瀛樺湪鍐呴儴鍑芥暟鏃讹紝鎵嶅彲浠ュ垱寤哄瓨鍌ㄨ繃绋嬶紒',
+          duration: 10
+        })
+        return
+      }
+
+      if (setting.dataresource.length > 50 && config.setting.dataresource !== setting.dataresource) {
+        let param = {
+          func: 's_DataSrc_Save',
+          LText: setting.dataresource,
+          MenuID: menu.MenuID
+        }
+
+        param.LText = Utils.formatOptions(param.LText)
+        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+        Api.getLocalConfig(param)
+      }
+
+      this.setState({
+        funcLoading: true
+      })
+
+      let newLText = Utils.formatOptions(Utils.getTableFunc(setting, menu, config)) // 鍒涘缓瀛樺偍杩囩▼sql
+      let DelText = Utils.formatOptions(Utils.dropfunc(setting.innerFunc))          // 鍒犻櫎瀛樺偍杩囩▼sql
+
+      new Promise(resolve => {
+        let sysDefer = new Promise(resolve => {
+          Api.getSystemConfig({
+            func: 'sPC_Get_TVP', // 浜戠鑾峰彇瀛樺偍缁撴灉
+            TVPName: setting.innerFunc
+          }).then(result => {
+            if (!result.status) {
+              notification.warning({
+                top: 92,
+                message: result.message,
+                duration: 10
+              })
+              resolve(false)
+            } else {
+              resolve(result)
+            }
+          })
+        })
+
+        let localDefer = new Promise(resolve => {
+          let _param = { // 鑾峰彇鏈湴瀛樺偍杩囩▼淇℃伅
+            func: 's_get_userproc',
+            LText: setting.innerFunc
+          }
+          _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+          _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+          
+          Api.getLocalConfig(_param).then(result => {
+            if (!result.status) {
+              notification.warning({
+                top: 92,
+                message: result.message,
+                duration: 10
+              })
+              resolve(false)
+            } else {
+              resolve(result)
+            }
+          })
+        })
+        
+        Promise.all([sysDefer, localDefer]).then(result => {
+          resolve(result)
+        })
+      }).then(res => {
+        // 鑾峰彇浜戠鍙婃湰鍦帮紝鏄惁宸插瓨鍦ㄨ瀛樺偍杩囩▼鐨勪俊鎭�
+        if (res === false) return res
+        if (res[0] === false || res[1] === false) return false
+
+        let cloudfunc = ''
+        let localfunc = ''
+        res.forEach((item, index) => {
+          if (index === 0 && item.TVPText) {
+            cloudfunc = item.TVPText
+          } else if (index === 1 && item.Ltext) {
+            localfunc = Utils.formatOptions(item.Ltext)
+          }
+        })
+
+        if ((newLText === localfunc) && (newLText === cloudfunc)) {
+          return 'drop'
+        } else if (!localfunc || (cloudfunc === localfunc)) {
+          // 鏈湴瀛樺偍杩囩▼涓嶅瓨鍦紝鎴栦簯绔拰鏈湴瀛樺偍杩囩▼涓�鑷存椂锛屽皢鏂扮殑瀛樺偍杩囩▼鏇存柊鑷充簯绔�
+          return Api.getSystemConfig({
+            func: 'sPC_TVP_InUp',
+            TVPName: setting.innerFunc,
+            TVPText: newLText,
+            TypeName: 'P'
+          })
+        } else {
+          return new Promise(resolve => {
+            Api.getSystemConfig({ // 娣诲姞鐜版湁鐨勬湰鍦板瓨鍌ㄨ繃绋嬭嚦浜戠
+              func: 'sPC_TVP_InUp',
+              TVPName: setting.innerFunc,
+              TVPText: localfunc,
+              TypeName: 'P'
+            }).then(result => {
+              if (result.status) {
+                Api.getSystemConfig({
+                  func: 'sPC_TVP_InUp', // 娣诲姞鏈�鏂扮殑瀛樺偍杩囩▼鑷充簯绔�
+                  TVPName: setting.innerFunc,
+                  TVPText: newLText,
+                  TypeName: 'P'
+                }).then(response => {
+                  resolve(response)
+                })
+              } else {
+                resolve(result)
+              }
+            })
+          })
+        }
+      }).then(res => {
+        // 浜戠淇℃伅鏇存柊鍚庯紝鍒ゆ柇鏄垹闄ゆ垨鏄洿鎺ユ柊寤哄瓨鍌ㄨ繃绋�
+        if (res === false || res === 'drop') return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else {
+          return 'create'
+        }
+      }).then(res => {
+        // 鍒犻櫎瀛樺偍杩囩▼
+        if (res === false || res === 'create') return res
+
+        let _param = {
+          func: 'sPC_TableData_InUpDe',
+          LText: DelText,
+          TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋�
+        }
+
+        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+
+        return Api.getLocalConfig(_param)
+      }).then(res => {
+        // 鏍规嵁涓婅堪鎿嶄綔缁撴灉锛屽垽鏂槸鍚︽柊寤哄瓨鍌ㄨ繃绋�
+        if (res === false || res === 'create') return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else {
+          return 'create'
+        }
+      }).then(res => {
+        // 鏂板缓瀛樺偍杩囩▼
+        if (res === false) return res
+
+        let _param = {
+          func: 'sPC_TableData_InUpDe',
+          LText: newLText,
+          TypeCharOne: 'proc' // 鍒犻櫎鎴栧垱寤哄瓨鍌ㄨ繃绋�
+        }
+        _param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        _param.secretkey = Utils.encrypt(_param.LText, _param.timestamp)
+
+        return Api.getLocalConfig(_param)
+      }).then(res => {
+        // 澶勭悊鏂板缓缁撴灉
+        if (res === false) return res
+
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+          return false
+        } else {
+          notification.success({
+            top: 92,
+            message: '鍒涘缓鎴愬姛',
+            duration: 2
+          })
+          return true
+        }
+      }).then(res => {
+        // 鏂板缓鎴愬姛鍚庯紝鏇存柊椤甸潰鎸夐挳淇℃伅
+        if (res === false) {
+          this.setState({
+            funcLoading: false
+          })
+          return
+        }
+
+        this.setState({
+          config: {...config, setting: setting}
+        })
+      })
+    })
+  }
+
+  deleteElement = (element) => {
+    let _this = this
+    confirm({
+      content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`,
+      okText: this.state.dict['header.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+        let _config = JSON.parse(JSON.stringify(_this.state.config))
+
+        if (element.type === 'tabs') {
+          _config[element.card.groupId] = _config[element.card.groupId].filter(item => {
+            if (item.uuid === element.card.uuid) {
+              return false
+            } else {
+              return true
+            }
+          })
+        } else {
+          _config[element.type] = _config[element.type].filter(item => {
+            if (item.uuid === element.card.uuid) {
+              return false
+            } else {
+              return true
+            }
+          })
+        }
+
+        let refreshtype = element.type + 'loading'
+
+        if (/^tab/.test(refreshtype)) {
+          refreshtype = 'tabloading'
+        }
+
+        _this.setState({
+          config: _config,
+          delActions: [..._this.state.delActions, element.card.uuid],
+          [refreshtype]: true
+        }, () => {
+          _this.setState({
+            [refreshtype]: false
+          })
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 楠岃瘉淇℃伅閰嶇疆
+   */
+  profileAction = (element) => {
+    this.setState({
+      profileVisible: true,
+      card: element
+    })
+  }
+
+  /**
+   * @description 楠岃瘉淇℃伅淇濆瓨
+   */
+  verifySubmit = () => {
+    const { card } = this.state
+    let config = JSON.parse(JSON.stringify(this.state.config))
+    let _verify = this.verifyRef.state.verify
+
+    config.action = config.action.map(item => {
+      if (item.uuid === card.uuid) {
+        item.verify = _verify
+      }
+
+      return item
+    })
+
+    this.setState({
+      profileVisible: false,
+      config: config,
+      card: '',
+      actionloading: true
+    }, () => {
+      this.setState({
+        actionloading: false
+      })
+    })
+  }
+
+  /**
+   * @description 涓夌骇鑿滃崟鍒囨崲妯℃澘
+   */
+  changeTemplate = () => {
+    this.props.handleConfig('template')
+  }
+
+  /**
+   * @description 涓夌骇鑿滃崟淇濆瓨
+   */
+  submitConfig = () => {
+    const { menu } = this.props
+    const { originMenu } = this.state
+
+    let config = JSON.parse(JSON.stringify(this.state.config))
+
+    this.menuformRef.handleConfirm().then(res => {
+
+      if (config.search[0] && config.search[0].origin) {
+        config.search = config.search.filter(item => !item.origin)
+      }
+      if (config.action[0] && config.action[0].origin) {
+        config.action = config.action.filter(item => !item.origin)
+      }
+      if (config.columns[0] && config.columns[0].origin) {
+        config.columns = config.columns.filter(item => !item.origin)
+      }
+      if (config.tabs[0] && config.tabs[0].origin) {
+        config.tabs = config.tabs.filter(item => !item.origin)
+      }
+
+      let _LongParam = ''
+      let _config = {...config, tables: this.state.selectedTables}
+      let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+
+      // 鏈缃暟鎹簮鎴栨爣绛句笉鍚堟硶鏃讹紝鍚敤鐘舵�佷负false
+      if (_config.setting.interType === 'inner' && !_config.setting.innerFunc && !_config.setting.dataresource) {
+        _config.enabled = false
+      } else if (_config.tabgroups.length > 1) {
+        _config.tabgroups.forEach(group => {
+          if (_config[group].length === 0) {
+            _config.enabled = false
+          }
+        })
+      }
+
+      // 淇濆瓨鏃跺垹闄ら厤缃被鍨嬶紝system 銆乽ser
+      delete _config.type
+
+      try {
+        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
+      } catch (e) {
+        notification.warning({
+          top: 92,
+          message: '缂栬瘧閿欒',
+          duration: 10
+        })
+        return
+      }
+
+      let btnParam = { // 娣诲姞鑿滃崟鎸夐挳
+        func: 'sPC_Button_AddUpt',
+        ParentID: menu.MenuID,
+        MenuNo: res.menuNo,
+        Template: menu.PageParam.Template || '',
+        PageParam: '',
+        LongParam: '',
+        LText: config.action.map((item, index) => {
+          return `select '${item.uuid}' as menuid, '${item.label}' as menuname, '${(index + 1) * 10}' as Sort`
+        })
+      }
+
+      btnParam.LText = btnParam.LText.join(' union all ')
+      btnParam.LText = Utils.formatOptions(btnParam.LText)
+      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
+      
+      let tabParam = { // 娣诲姞鑿滃崟tab椤�
+        func: 'sPC_sMenusTab_AddUpt',
+        MenuID: menu.MenuID,
+        LText: config.tabs.map((item, index) => {
+          return `select '${menu.MenuID}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${(index + 1) * 10}' as Sort`
+        })
+      }
+      tabParam.LText = tabParam.LText.join(' union all ')
+      tabParam.LText = Utils.formatOptions(tabParam.LText)
+      tabParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+      tabParam.secretkey = Utils.encrypt(tabParam.LText, tabParam.timestamp)
+
+      let param = {
+        func: 'sPC_TrdMenu_AddUpt',
+        ParentID: res.parentId,
+        MenuID: menu.MenuID,
+        MenuNo: res.menuNo,
+        Template: menu.PageParam.Template || '',
+        MenuName: res.menuName,
+        Sort: (this.props.supMenuList.length + 1) * 10,
+        PageParam: JSON.stringify(_pageParam),
+        LongParam: _LongParam
+      }
+      
+      if (this.state.closeVisible) { // 鏄剧ず鍏抽棴瀵硅瘽妗嗘椂锛屾ā鎬佹涓繚瀛樻寜閽紝鏄剧ず淇濆瓨涓姸鎬�
+        this.setState({
+          menucloseloading: true
+        })
+      } else {
+        this.setState({
+          menuloading: true
+        })
+      }
+
+      Api.getSystemConfig(param).then(response => {
+        if (response.status) {
+          this.setState({
+            config: _config,
+            originMenu: {
+              ...originMenu,
+              LongParam: _config,
+              PageParam: _pageParam,
+              MenuName: res.menuName,
+              MenuNo: res.menuNo,
+              ParentID: res.parentId
+            },
+            searchloading: true,
+            actionloading: true,
+            columnsloading: true
+          }, () => {
+            this.setState({
+              searchloading: false,
+              actionloading: false,
+              columnsloading: false
+            })
+          })
+
+          this.props.reloadmenu()
+          
+          this.submitAction(btnParam, tabParam)
+        } else {
+          this.setState({
+            menuloading: false,
+            menucloseloading: false
+          })
+          notification.warning({
+            top: 92,
+            message: response.message,
+            duration: 10
+          })
+        }
+      })
+    }, () => {
+      notification.warning({
+        top: 92,
+        message: this.state.dict['header.menu.basemsg'],
+        duration: 10
+      })
+    })
+  }
+
+  /**
+   * @description 淇濆瓨鎴栦慨鏀硅彍鍗曟寜閽�
+   */
+  submitAction = (btnParam, tabParam) => {
+    const { config } = this.state
+    new Promise(resolve => {
+      // 鍐呴儴璇锋眰
+      if (this.state.delActions.length > 0) {
+        let deffers = this.state.delActions.map(item => {
+          let _param = {
+            func: 'sPC_MainMenu_Del',
+            MenuID: item
+          }
+          return new Promise(resolve => {
+            Api.getSystemConfig(_param).then(res => {
+              resolve(res)
+            })
+          })
+        })
+        Promise.all(deffers).then(result => {
+          let error = false
+          result.forEach(res => {
+            if (!res.status) {
+              error = res
+            }
+          })
+
+          if (error) {
+            notification.warning({
+              top: 92,
+              message: error.message,
+              duration: 10
+            })
+            resolve(false)
+          } else {
+            this.setState({
+              delActions: []
+            })
+            resolve(true)
+          }
+        })
+      } else if (this.state.delActions.length === 0) {
+        resolve(true)
+      }
+    }).then(res => {
+      if (res === false) return res
+
+      if (tabParam.LText) {
+        Api.getSystemConfig(tabParam).then(result => {
+          if (!result.status) {
+            notification.warning({
+              top: 92,
+              message: result.message,
+              duration: 10
+            })
+          }
+        })
+      }
+      if (btnParam.LText) {
+        return Api.getSystemConfig(btnParam)
+      } else {
+        return 'copy'
+      }
+    }).then(response => {
+      if (response === false || response === 'copy') return response
+
+      if (response.status) {
+        return 'copy'
+      } else {
+        notification.warning({
+          top: 92,
+          message: response.message,
+          duration: 10
+        })
+        return false
+      }
+    }).then(response => {
+      if (response === false) return response
+
+      let oriActions = []
+      this.state.originActions.forEach(item => {
+        let curBtn = config.action.filter(cell => item.curuuid === cell.uuid)[0] // 鏌ョ湅鍒濆鍖栨寜閽槸鍚﹀瓨鍦�
+        if (!curBtn) return
+        if (curBtn.OpenType !== item.prebtn.OpenType) return
+
+        oriActions.push({
+          prebtn: item.prebtn,
+          curBtn: curBtn
+        })
+      })
+
+      if (oriActions.length === 0) return 'true'
+
+      oriActions.forEach(action => {
+        Api.getSystemConfig({
+          func: 'sPC_Get_LongParam',
+          MenuID: action.prebtn ? action.prebtn.uuid : ''
+        }).then(result => {
+          if (result.status && result.LongParam) {
+            let _LongParam = ''
+  
+            if (result.LongParam) {
+              _LongParam = window.decodeURIComponent(window.atob(result.LongParam))
+              try {
+                _LongParam = JSON.parse(_LongParam)
+              } catch (e) {
+                _LongParam = ''
+              }
+            }
+
+            if (_LongParam) {
+              let param = {
+                func: 'sPC_ButtonParam_AddUpt',
+                ParentID: this.props.menu.MenuID,
+                MenuID: action.curBtn.uuid,
+                MenuNo: this.props.menu.MenuNo,
+                Template: _LongParam.type,
+                MenuName: action.curBtn.label,
+                PageParam: JSON.stringify({Template: _LongParam.type}),
+                LongParam: result.LongParam
+              }
+              Api.getSystemConfig(param).then(() => {})
+            }
+          }
+        })
+      })
+      return 'true'
+    }).then(response => {
+      if (response === 'true') {
+        notification.success({
+          top: 92,
+          message: '淇濆瓨鎴愬姛',
+          duration: 2
+        })
+        if (this.state.closeVisible) {
+          this.props.handleConfig('')
+        } else {
+          this.setState({
+            menuloading: false,
+            menucloseloading: false
+          })
+        }
+      } else {
+        this.setState({
+          menuloading: false,
+          menucloseloading: false
+        })
+      }
+    })
+  }
+
+  cancelConfig = () => {
+    const { menu } = this.props
+    const { config, originMenu } = this.state
+
+    let _this = this
+    let isAdd = false
+
+    if (
+      (config.search[0] && config.search[0].origin) ||
+      (config.action[0] && config.action[0].origin) ||
+      (config.columns[0] && config.columns[0].origin) ||
+      (config.tabs[0] && config.tabs[0].origin)
+    ) {
+      isAdd = true
+    }
+
+    if (isAdd) {
+      confirm({
+        content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
+        okText: this.state.dict['header.confirm'],
+        cancelText: this.state.dict['header.cancel'],
+        onOk() {
+          _this.props.handleConfig('')
+        },
+        onCancel() {}
+      })
+    } else {
+      this.menuformRef.handleConfirm().then(res => {
+        let _config = {...config, tables: this.state.selectedTables}
+        let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+        let _originMenu = {
+          ...originMenu,
+          LongParam: _config,
+          PageParam: _pageParam,
+          MenuName: res.menuName,
+          MenuNo: res.menuNo,
+          ParentID: res.parentId
+        }
+
+        if (!is(fromJS(originMenu), fromJS(_originMenu))) {
+          this.setState({
+            closeVisible: true
+          })
+        } else {
+          this.props.handleConfig('')
+        }
+      }, () => {
+        this.setState({
+          closeVisible: true
+        })
+      })
+    }
+  }
+
+  queryField = (type) => {
+    const {selectedTables, tableColumns, config} = this.state
+    // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕
+    if (selectedTables.length === 0) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨琛ㄥ悕锛�',
+        duration: 10
+      })
+      return
+    }
+
+    // 琛ㄥ瓧娈甸泦杞负map鏁版嵁
+    let columns = new Map()
+    tableColumns.forEach(table => {
+      table.columns.forEach(column => {
+        columns.set(column.field, column)
+      })
+    })
+
+    if (type === 'search') {
+      // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷
+      config.search.forEach(item => {
+        if (columns.has(item.field)) {
+          let _datatype = columns.get(item.field).datatype
+          columns.set(item.field, {...item, selected: true, datatype: _datatype})
+        }
+      })
+    } else if (type === 'columns') {
+      // 娣诲姞鏄剧ず鍒楋紝瀛楁闆嗕腑瀛樺湪鏄剧ず鍒楀瓧娈碉紝浣跨敤鏄剧ず鍒楀璞℃浛鎹㈠瓧娈甸泦锛岃缃暟鎹被鍨�
+      config.columns.forEach(item => {
+        if (columns.has(item.field)) {
+          let _datatype = columns.get(item.field).datatype
+          columns.set(item.field, {...item, selected: true, datatype: _datatype})
+        }
+      })
+    }
+
+    // 鏄剧ず瀛楁闆嗗脊绐�
+    this.setState({
+      addType: type,
+      tableVisible: true,
+      fields: [...columns.values()]
+    })
+  }
+
+  addFieldSubmit = () => {
+    // 瀛楁闆嗕负绌猴紝鍏抽棴寮圭獥
+    if (!this.state.fields || this.state.fields.length === 0) {
+      this.setState({
+        tableVisible: false,
+        addType: ''
+      })
+    }
+
+    const {addType, config} = this.state
+    const textmatch = { // 閫夋嫨text鏃跺尮閰嶈鍒�
+      text: 'like',
+      number: 'like',
+      datetime: 'like',
+      date: 'like'
+    }
+    const selectmatch = { // 閫夋嫨select鏃跺尮閰嶈鍒�
+      text: '=',
+      number: '=',
+      datetime: '=',
+      date: '='
+    }
+    const datematch = { // 閫夋嫨dateRange鏃跺尮閰嶈鍒�
+      text: 'between',
+      number: 'between',
+      datetime: 'between',
+      date: 'between'
+    }
+
+    // 鑾峰彇宸查�夊瓧娈甸泦鍚�
+    let cards = this.refs.searchcard.state.selectCards
+    let columnsMap = new Map()
+    cards.forEach(card => {
+      columnsMap.set(card.field, card)
+    })
+
+    let items = []
+    if (addType === 'search') {
+      config.search.forEach(item => {
+        if (columnsMap.has(item.field)) {
+          let cell = columnsMap.get(item.field)
+
+          if (cell.selected && cell.type === item.type) { // 鏁版嵁鏈慨鏀�
+            items.push(item)
+          } else if (cell.selected) { // 鏁版嵁绫诲瀷淇敼
+            if (cell.type === 'text') {
+              item.match = textmatch[cell.datatype]
+            } else if (cell.type === 'select') {
+              item.match = selectmatch[cell.datatype]
+            } else if (cell.type === 'daterange') {
+              item.match = datematch[cell.datatype]
+            } else {
+              cell.type = 'text'
+              item.match = textmatch[cell.datatype]
+            }
+            
+            item.type = cell.type
+            item.initval = ''
+            items.push(item)
+          }
+          columnsMap.delete(item.field)
+        } else if (!item.origin) {
+          items.push(item)
+        }
+      })
+
+      let _columns = [...columnsMap.values()]
+
+      _columns.forEach(item => {
+        if (item.selected) {
+          let _match = ''
+          if (item.type === 'text') {
+            _match = textmatch[item.datatype]
+          } else if (item.type === 'select') {
+            _match = selectmatch[item.datatype]
+          } else if (item.type === 'daterange') {
+            _match = datematch[item.datatype]
+          } else {
+            item.type = 'text'
+            _match = textmatch[item.datatype]
+          }
+
+          let newcard = {
+            uuid: Utils.getuuid(),
+            label: item.label,
+            field: item.field,
+            initval: '',
+            type: item.type,
+            resourceType: '0',
+            setAll: 'false',
+            options: [],
+            dataSource: '',
+            linkField: '',
+            valueField: '',
+            valueText: '',
+            orderBy: '',
+            orderType: 'asc',
+            match: _match,
+            display: 'dropdown'
+          }
+
+          items.push(newcard)
+        }
+      })
+    } else {
+      config.columns.forEach(item => {
+        if (columnsMap.has(item.field)) {
+          let cell = columnsMap.get(item.field)
+
+          if (cell.selected) {
+            items.push(item)
+          }
+          columnsMap.delete(item.field)
+        } else if (!item.origin) {
+          items.push(item)
+        }
+      })
+
+      let _columns = [...columnsMap.values()]
+
+      _columns.forEach(item => {
+        if (item.selected) {
+          let newcard = {
+            uuid: Utils.getuuid(),
+            Align: 'left',
+            label: item.label,
+            field: item.field,
+            Hide: 'false',
+            IsSort: item.type === 'picture' ? 'false' : 'true',
+            type: item.type,
+            Width: 120
+          }
+
+          items.push(newcard)
+        }
+      })
+    }
+
+    this.setState({
+      [addType + 'loading']: true,
+      config: {...config, [addType]: items}
+    }, () => {
+      notification.success({
+        top: 92,
+        message: '鎿嶄綔鎴愬姛',
+        duration: 2
+      })
+      this.setState({
+        [addType + 'loading']: false
+      })
+    })
+  }
+
+  onTableChange = (value) => {
+    const {tables, selectedTables, tableColumns} = this.state
+
+    let _table = tables.filter(item => item.TbName === value)[0]
+    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
+    if (!isSelected) {
+      this.setState({
+        selectedTables: [...selectedTables, _table]
+      })
+      Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
+        if (res.status) {
+          let tabmsg = {
+            tableName: _table.name,
+            columns: res.FDName.map(item => {
+              let _type = item.FieldType.toLowerCase()
+              let _decimal = 0
+              if (/^nvarchar/.test(_type)) {
+                _type = 'text'
+              } else if (/^int/.test(_type)) {
+                _type = 'number'
+              } else if (/^decimal/.test(_type)) {
+                _decimal = _type.split(',')[1]
+                _decimal = parseInt(_decimal)
+                _type = 'number'
+              } else if (/^datetime/.test(_type)) {
+                _type = 'datetime'
+              } else if (/^date/.test(_type)) {
+                _type = 'date'
+              } else {
+                _type = 'text'
+              }
+
+              return {
+                field: item.FieldName,
+                label: item.FieldDec,
+                type: _type,
+                datatype: _type,
+                decimal: _decimal
+              }
+            })
+          }
+          this.setState({
+            tableColumns: [...tableColumns, tabmsg]
+          })
+        } else {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+        }
+      })
+    }
+  }
+
+  deleteTable = (table) => {
+    const {selectedTables, tableColumns} = this.state
+
+    this.setState({
+      selectedTables: selectedTables.filter(item => item.TbName !== table.TbName),
+      tableColumns: tableColumns.filter(item => item.tableName !== table.TbName)
+    })
+  }
+
+  changeSetting = () => {
+    this.setState({
+      settingVisible: true
+    })
+  }
+
+  settingSave = () => {
+    const { menu } = this.props
+    const {config} = this.state
+
+    this.settingRef.handleConfirm().then(res => {
+      if (
+        res.interType === 'inner' &&
+        !res.innerFunc &&
+        res.dataresource.length > 50 &&
+        config.setting.dataresource !== res.dataresource
+      ) {
+        let param = {
+          func: 's_DataSrc_Save',
+          LText: res.dataresource,
+          MenuID: menu.MenuID
+        }
+
+        param.LText = Utils.formatOptions(param.LText)
+        param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+        param.secretkey = Utils.encrypt(param.LText, param.timestamp)
+
+        Api.getLocalConfig(param)
+      }
+
+      this.setState({
+        config: {...config, setting: res},
+        settingVisible: false,
+        columnsloading: true,
+        tabloading: true
+      }, () => {
+        this.setState({
+          columnsloading: false,
+          tabloading: false
+        })
+      })
+    })
+  }
+
+  /**
+   * @description 璁剧疆鍙厤缃寜閽�
+   */
+  setSubConfig = (btn, type) => {
+    const { menu } = this.props
+    const { config, originMenu } = this.state
+
+    let isAdd = false
+
+    if (
+      (config.search[0] && config.search[0].origin) ||
+      (config.action[0] && config.action[0].origin) ||
+      (config.columns[0] && config.columns[0].origin) ||
+      (config.tabs[0] && config.tabs[0].origin)
+    ) {
+      isAdd = true
+    }
+
+    if (isAdd) {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟灏氭湭淇濆瓨锛岃淇濆瓨鑿滃崟閰嶇疆锛�',
+        duration: 10
+      })
+    } else {
+      this.menuformRef.handleConfirm().then(res => {
+        let _config = {...config, tables: this.state.selectedTables}
+        let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+        let _originMenu = {
+          ...originMenu,
+          LongParam: _config,
+          PageParam: _pageParam,
+          MenuName: res.menuName,
+          MenuNo: res.menuNo,
+          ParentID: res.parentId
+        }
+
+        if (!is(fromJS(originMenu), fromJS(_originMenu))) {
+          notification.warning({
+            top: 92,
+            message: '鑿滃崟閰嶇疆宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
+            duration: 10
+          })
+        } else {
+          this.setState({
+            loading: true
+          })
+
+          let uuid = ''
+          let _type = type
+          if (type === 'button' && btn.OpenType === 'popview') {
+            _type = 'tab'
+          }
+
+          if (_type === 'button') {
+            uuid = btn.uuid
+          } else {
+            uuid = btn.linkTab
+          }
+
+          Api.getSystemConfig({
+            func: 'sPC_Get_LongParam',
+            MenuID: uuid
+          }).then(res => {
+            if (res.status) {
+              this.setState({
+                loading: false
+              })
+              let _LongParam = ''
+              if (res.LongParam) {
+                _LongParam = window.decodeURIComponent(window.atob(res.LongParam))
+                try {
+                  _LongParam = JSON.parse(_LongParam)
+                } catch (e) {
+                  _LongParam = ''
+                }
+              }
+
+              if (_type === 'tab' && !_LongParam) {
+                _LongParam = {
+                  ...btn,
+                  uuid: btn.linkTab,
+                  create: true
+                }
+              }
+
+              this.props.handleSubConfig(btn, originMenu, _LongParam, _type)
+            } else {
+              this.setState({
+                loading: false
+              })
+              notification.warning({
+                top: 92,
+                message: res.message,
+                duration: 10
+              })
+            }
+          })
+        }
+      }, () => {
+        notification.warning({
+          top: 92,
+          message: '鑿滃崟鍩烘湰淇℃伅宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
+          duration: 10
+        })
+      })
+    }
+  }
+
+  onEnabledChange = (val, e) => {
+    const { config } = this.state
+
+    let tabinvalid = true
+    if (config.tabgroups.length > 1) {
+      config.tabgroups.forEach(group => {
+        if (config[group].length === 0) {
+          tabinvalid = false
+        }
+      })
+    }
+
+    if (config.setting.interType === 'inner' && !config.setting.innerFunc && !config.setting.dataresource) {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟灏氭湭璁剧疆鏁版嵁婧愶紝涓嶅彲鍚敤锛�',
+        duration: 10
+      })
+    } else if (!tabinvalid) {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟鏍囩椤佃缃敊璇紙澶氳鏍囩鍐咃紝琛屾爣绛句笉鍙负绌猴級锛屼笉鍙惎鐢紒',
+        duration: 10
+      })
+    } else {
+      this.setState({
+        config: {...config, enabled: !config.enabled}
+      })
+    }
+  }
+
+  onColumnNameChange = () => {
+    const { showColumnName } = this.state
+
+    this.setState({
+      showColumnName: !showColumnName
+    })
+  }
+
+  addTabGroup = () => {
+    let _this = this
+    let _config = JSON.parse(JSON.stringify(this.state.config))
+
+    confirm({
+      content: `纭畾鏂板缓鏍囩缁勫悧锛焋,
+      okText: this.state.dict['header.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+        let newgroup = 'tabs' + Utils.getuuid()
+
+        _config.tabgroups.push(newgroup)
+        _config[newgroup] = []
+
+        _this.setState({
+          config: _config,
+          tabloading: true
+        }, () => {
+          _this.setState({
+            tabloading: false
+          })
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  delTabGroup = (groupId) => {
+    let _this = this
+    let _config = JSON.parse(JSON.stringify(this.state.config))
+
+    confirm({
+      content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋,
+      okText: this.state.dict['header.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+
+        _config.tabgroups = _config.tabgroups.filter(group => group !== groupId)
+        delete _config[groupId]
+
+        _this.setState({
+          config: _config,
+          tabloading: true
+        }, () => {
+          _this.setState({
+            tabloading: false
+          })
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  render () {
+    const configAction = this.state.config.action.filter(_action =>
+      !_action.origin && (_action.OpenType === 'pop' || _action.OpenType === 'popview' || _action.OpenType === 'blank' || _action.OpenType === 'tab')
+    )
+
+    let configTabs = []
+    this.state.config.tabgroups.forEach(group => {
+      configTabs.push(...this.state.config[group])
+    })
+
+    return (
+      <div className="common-table-board">
+        <DndProvider backend={HTML5Backend}>
+          {/* 宸ュ叿鏍� */}
+          <div className="tools">
+            <Collapse accordion defaultActiveKey="0" bordered={false}>
+              {/* 鍩烘湰淇℃伅 */}
+              <Panel header={this.state.dict['header.menu.basedata']} key="0" id="common-basedata">
+                {/* 鑿滃崟淇℃伅 */}
+                <MenuForm
+                  dict={this.state.dict}
+                  formlist={this.state.menuformlist}
+                  wrappedComponentRef={(inst) => this.menuformRef = inst}
+                />
+                {/* 琛ㄥ悕娣诲姞 */}
+                <div className="ant-col ant-form-item-label">
+                  <label>
+                    <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽湪娣诲姞鎼滅储鏉′欢鍜屾樉绀哄垪鏃讹紝鍙�氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鎵归噺娣诲姞琛ㄦ牸鐩稿叧瀛楁銆�">
+                      <Icon type="question-circle" />
+                      {this.state.dict['header.menu.table.add']}
+                    </Tooltip>
+                  </label>
+                </div>
+                <Select
+                  showSearch
+                  className="tables"
+                  style={{ width: '100%' }}
+                  optionFilterProp="children"
+                  value={this.state.dict['header.menu.table.placeholder']}
+                  onChange={this.onTableChange}
+                  showArrow={false}
+                  getPopupContainer={() => document.getElementById('common-basedata')}
+                  filterOption={(input, option) => {
+                    return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
+                      option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                  }}
+                > 
+                  {this.state.tables.map((table, index) => (
+                    <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option>
+                  ))}
+                </Select>
+                {this.state.selectedTables.length > 0 && <List
+                  size="small"
+                  bordered
+                  dataSource={this.state.selectedTables}
+                  renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
+                    {item.Remark + ' (' + item.TbName + ')'}
+                    <Icon type="close" onClick={() => this.deleteTable(item)}/>
+                    <div className="bottom-mask"></div>
+                  </List.Item>}
+                />}
+              </Panel>
+              {/* 鎼滅储鏉′欢娣诲姞 */}
+              <Panel header={this.state.dict['header.menu.search']} key="1">
+                <div className="search-element">
+                  {Source.searchItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                <Button type="primary" block onClick={() => this.queryField('search')}>{this.state.dict['header.menu.search.add']}</Button>
+              </Panel>
+              {/* 鎸夐挳娣诲姞 */}
+              <Panel header={this.state.dict['header.menu.action']} key="2">
+                <div className="search-element">
+                  {Source.actionItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                {configAction.length > 0 ?
+                  <p className="config-btn-title">
+                    <Tooltip placement="topLeft" title="鐐瑰嚮鎸夐挳锛屽彲瀹屾垚鎴栨煡鐪嬫寜閽厤缃俊鎭��">
+                      <Icon type="question-circle" />
+                    </Tooltip>
+                    {this.state.dict['header.menu.action.configurable']}
+                  </p> : null
+                }
+                {configAction.map((item, index) => {
+                  return (
+                    <div key={index}>
+                      <Button
+                        icon={item.icon}
+                        style={{marginBottom: '10px'}}
+                        className={'config-button mk-btn mk-' + item.class}
+                        onClick={() => this.setSubConfig(item, 'button')}
+                      >{item.label}</Button>
+                    </div>
+                  )
+                })}
+              </Panel>
+              {/* 娣诲姞鏄剧ず鍒� */}
+              <Panel header={this.state.dict['header.menu.column']} key="3">
+                <div className="search-element">
+                  {Source.columnItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                <Button type="primary" block onClick={() => this.queryField('columns')}>{this.state.dict['header.menu.column.add']}</Button>
+              </Panel>
+              {/* 娣诲姞鏍囩 */}
+              <Panel header={this.state.dict['header.menu.tab']} key="4">
+                <div className="search-element">
+                  {Source.tabItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                {configTabs.length > 0 ?
+                  <p className="config-btn-title">
+                    <Tooltip placement="topLeft" title="鐐瑰嚮鎸夐挳锛屽彲瀹屾垚鎴栨煡鐪嬫爣绛鹃厤缃俊鎭��">
+                      <Icon type="question-circle" />
+                    </Tooltip>
+                    {this.state.dict['header.menu.tab.configurable']}
+                  </p> : null
+                }
+                {configTabs.map((item, index) => {
+                  return (
+                    <div key={index}>
+                      <Button
+                        className="config-button"
+                        icon={item.icon}
+                        style={{marginBottom: '10px'}}
+                        onClick={() => this.setSubConfig(item, 'tab')}
+                      >{item.label}</Button>
+                    </div>
+                  )
+                })}
+              </Panel>
+            </Collapse>
+          </div>
+          <div className="setting">
+            <Card title={this.state.dict['header.menu.page.configurable']} bordered={false} extra={
+              <div>
+                <Switch className="big" checkedChildren="鍚�" unCheckedChildren="鍋�" checked={this.state.config.enabled} onChange={this.onEnabledChange} />
+                <Button type="primary" onClick={this.changeTemplate}>{this.state.dict['header.menu.template.change']}</Button>
+                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
+                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
+              </div>
+            } style={{ width: '100%' }}>
+              <Icon type="setting" onClick={this.changeSetting} />
+              <div className="search-list">
+                <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��">
+                  <Icon type="question-circle" />
+                </Tooltip>
+                {!this.state.searchloading ?
+                  <DragElement
+                    type="search"
+                    list={this.state.config.search}
+                    handleList={this.handleList}
+                    handleMenu={this.handleSearch}
+                    deleteMenu={this.deleteElement}
+                    placeholder={this.state.dict['header.form.search.placeholder']}
+                  /> : null
+                }
+              </div>
+              <div className="action-list">
+                <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�">
+                  <Icon type="question-circle" />
+                </Tooltip>
+                {!this.state.actionloading ?
+                  <DragElement
+                    type="action"
+                    list={this.state.config.action}
+                    handleList={this.handleList}
+                    handleMenu={this.handleAction}
+                    copyElement={(val) => this.handleAction(val, 'copy')}
+                    deleteMenu={this.deleteElement}
+                    profileMenu={this.profileAction}
+                    placeholder={this.state.dict['header.form.action.placeholder']}
+                  /> : null
+                }
+              </div>
+              {/* 鏄剧ず鍒� */}
+              <div className="column-list">
+                <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�">
+                  <Icon type="question-circle" />
+                </Tooltip>
+                <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showColumnName} onChange={this.onColumnNameChange} />
+                {!this.state.columnsloading ?
+                  <DragElement
+                    type="columns"
+                    list={this.state.config.columns}
+                    setting={this.state.config.setting}
+                    gridBtn={this.state.config.gridBtn}
+                    handleList={this.handleList}
+                    handleMenu={this.handleColumn}
+                    deleteMenu={this.deleteElement}
+                    handleGridBtn={this.handleGridBtn}
+                    showfield={this.state.showColumnName}
+                    placeholder={this.state.dict['header.form.column.placeholder']}
+                  /> : null
+                }
+              </div>
+              {/* 鏍囩缁� */}
+              {!this.state.tabloading && this.state.config.tabgroups.map((groupId, index) => {
+                return (
+                  <div key={index} className="tab-list">
+                    {index === 0 ? <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃爣绛鹃〉銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬爣绛鹃〉鎷栬嚦姝ゅ娣诲姞銆�">
+                      <Icon type="question-circle" />
+                    </Tooltip> : null}
+                    {index === 0 ? <Icon type="plus" onClick={this.addTabGroup} /> : null}
+                    {index !== 0 ? <Icon type="delete" onClick={() => {this.delTabGroup(groupId)}} /> : null}
+                    <TabDragElement
+                      type="tabs"
+                      groupId={groupId}
+                      list={this.state.config[groupId]}
+                      handleList={this.handleList}
+                      handleMenu={this.handleTab}
+                      deleteMenu={this.deleteElement}
+                      placeholder={this.state.dict['header.form.tab.placeholder']}
+                    />
+                  </div>)
+              })}
+            </Card>
+          </div>
+        </DndProvider>
+        {/* 缂栬緫鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪 */}
+        <Modal
+          title={this.state.modalTitle}
+          visible={this.state.visible}
+          width={700}
+          onCancel={() => { this.setState({ visible: false }) }}
+          footer={[
+            this.state.formtemp === 'action' ?
+            <Button key="delete" className="mk-btn mk-purple" onClick={this.creatFunc} loading={this.state.funcLoading}>{this.state.dict['header.menu.func.create']}</Button> : null,
+            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>{this.state.dict['header.cancel']}</Button>,
+            <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button>
+          ]}
+          destroyOnClose
+        >
+          {this.state.formtemp === 'search' ?
+            <SearchForm
+              dict={this.state.dict}
+              formlist={this.state.formlist}
+              card={this.state.card}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+          {this.state.formtemp === 'action' ?
+            <ActionForm
+              dict={this.state.dict}
+              card={this.state.card}
+              tabs={this.state.tabviews}
+              formlist={this.state.formlist}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+          {this.state.formtemp === 'columns' && this.state.card.type !== 'colspan' ?
+            <ColumnForm
+              dict={this.state.dict}
+              card={this.state.card}
+              formlist={this.state.formlist}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+          {this.state.formtemp === 'columns' && this.state.card.type === 'colspan' ?
+            <ColspanForm
+              dict={this.state.dict}
+              card={this.state.card}
+              columns={this.state.config.columns}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+          {this.state.formtemp === 'gridbtn' ?
+            <GridBtnForm
+              dict={this.state.dict}
+              card={this.state.config.gridBtn}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+          {this.state.formtemp === 'tabs' ?
+            <TabForm
+              type="tabs"
+              tabs={this.state.tabviews}
+              dict={this.state.dict}
+              card={this.state.card}
+              formlist={this.state.formlist}
+              wrappedComponentRef={(inst) => this.formRef = inst}
+            /> : null
+          }
+        </Modal>
+        {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
+        <Modal
+          wrapClassName="common-table-fields-modal"
+          title={this.state.dict['header.edit']}
+          visible={this.state.tableVisible}
+          width={'65vw'}
+          style={{minWidth: '900px', maxWidth: '1200px'}}
+          cancelText={this.state.dict['header.close']}
+          onOk={this.addFieldSubmit}
+          onCancel={() => { // 鍙栨秷娣诲姞
+            this.setState({
+              tableVisible: false,
+              addType: ''
+            })
+          }}
+          destroyOnClose
+        >
+          {this.state.addType && this.state.fields.length > 0 ?
+            <EditCard data={this.state.fields} ref="searchcard" type={this.state.addType} dict={this.state.dict} /> : null
+          }
+          {(!this.state.fields || this.state.fields.length === 0) &&
+            <Empty />
+          }
+        </Modal>
+        {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
+        <Modal
+          wrapClassName="common-table-fields-modal"
+          title={'楠岃瘉淇℃伅'}
+          visible={this.state.profileVisible}
+          width={'75vw'}
+          style={{minWidth: '900px', maxWidth: '1200px'}}
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ profileVisible: false }) }}
+          destroyOnClose
+        >
+          <VerifyCard card={this.state.card} columns={this.state.config.columns} wrappedComponentRef={(inst) => this.verifyRef = inst} dict={this.state.dict} />
+        </Modal>
+        {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
+        <Modal
+          title={this.state.dict['header.edit']}
+          visible={this.state.settingVisible}
+          width={700}
+          // onOk={this.settingSave}
+          onCancel={() => { // 鍙栨秷淇敼
+            this.setState({
+              settingVisible: false
+            })
+          }}
+          footer={[
+            <Button key="delete" className="mk-btn mk-purple" onClick={this.tableCreatFunc} loading={this.state.funcLoading}>{this.state.dict['header.menu.func.create']}</Button>,
+            <Button key="cancel" onClick={() => { this.setState({ settingVisible: false }) }}>{this.state.dict['header.cancel']}</Button>,
+            <Button key="confirm" type="primary" onClick={this.settingSave}>{this.state.dict['header.confirm']}</Button>
+          ]}
+          destroyOnClose
+        >
+          <SettingForm
+            dict={this.state.dict}
+            menu={this.props.menu}
+            config={this.state.config}
+            data={this.state.config.setting}
+            columns={this.state.config.columns}
+            usefulFields={this.props.permFuncField}
+            wrappedComponentRef={(inst) => this.settingRef = inst}
+          />
+        </Modal>
+        <Modal
+          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
+          closable={false}
+          visible={this.state.closeVisible}
+          onCancel={() => { this.setState({closeVisible: false}) }}
+          footer={[
+            <Button key="save" className="mk-btn mk-green" loading={this.state.menucloseloading} onClick={this.submitConfig}>{this.state.dict['header.save']}</Button>,
+            <Button key="confirm" className="mk-btn mk-yellow" onClick={() => {this.props.handleConfig('')}}>{this.state.dict['header.notsave']}</Button>,
+            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['header.cancel']}</Button>
+          ]}
+          destroyOnClose
+        >
+          {this.state.dict['header.menu.config.placeholder']}
+        </Modal>
+        {this.state.loading && <Spin size="large" />}
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = (state) => {
+  return {
+    permFuncField: state.permFuncField
+  }
+}
+
+const mapDispatchToProps = () => {
+  return {}
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ComTableConfig)
diff --git a/src/templates/modalviewconfig/index.scss b/src/templates/modalviewconfig/index.scss
new file mode 100644
index 0000000..d1e5eea
--- /dev/null
+++ b/src/templates/modalviewconfig/index.scss
@@ -0,0 +1,515 @@
+.common-table-board {
+  position: fixed;
+  z-index: 1070;
+  padding-top: 48px;
+  top: 0px;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
+  background: rgba(0, 0, 0, 0.35);
+  display: flex;
+  .tools {
+    flex: 1;
+    background: #ffffff;
+    border-right: 1px solid #d9d9d9;
+    height: 100%;
+    overflow-y: hidden;
+    padding-bottom: 30px;
+    .ant-collapse-item {
+      position: relative;
+      border: 0;
+    }
+    .ant-input-search {
+      margin-top: 10px;
+    }
+    .ant-collapse-item.ant-collapse-item-active {
+      border-bottom: 1px solid #d9d9d9;
+    }
+    .ant-collapse-header {
+      padding: 11px 16px 10px 40px;
+      border-bottom: 1px solid #d9d9d9;
+      background: #1890ff;
+      color: #ffffff;
+    }
+    .ant-collapse-content-box {
+      .ant-form-item {
+        margin-bottom: 10px;
+        .ant-form-item-label {
+          text-align: left;
+          height: 25px;
+          line-height: 25px;
+        }
+      }
+    }
+    .search-element {
+      padding-top: 10px;
+      li {
+        padding: 0px 16px 10px;
+        div {
+          cursor: move;
+        }
+      }
+    }
+    .config-btn-title {
+      margin-top: 20px;
+      margin-bottom: 10px;
+      color: #1890ff;
+      border-bottom: 1px solid #e8e8e8;
+    }
+    .tables {
+      .ant-select-selection-selected-value {
+        opacity: 0.4!important;
+      }
+    }
+    .ant-list {
+      margin-top: 20px;
+      .ant-list-item {
+        display: -webkit-box;
+        padding-right: 20px;
+        position: relative;
+        padding-left: 5px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        -webkit-line-clamp: 2;
+        -webkit-box-orient: vertical;
+        min-height: 55px;
+        width: 100%;
+        .anticon {
+          position: absolute;
+          top: 0px;
+          right: 0px;
+          padding: 3px 3px 10px 10px;
+          cursor: pointer;
+        }
+        .bottom-mask {
+          position: absolute;
+          width: 100%;
+          height: 8px;
+          bottom: 0;
+          left: 0;
+          background: #ffffff;
+          border-radius: 8px;
+        }
+      }
+    }
+    .anticon-question-circle {
+      color: #c49f47;
+      margin-right: 3px;
+    }
+    .config-button {
+      min-width: 65px;
+    }
+  }
+  .tools:hover {
+    overflow-y: auto;
+  }
+  .tools::-webkit-scrollbar {
+    width: 7px;
+  }
+  .tools::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
+    background: rgba(0, 0, 0, 0);
+  }
+  .tools::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0);
+    background: rgba(0, 0, 0, 0);
+  }
+  .tools:hover::-webkit-scrollbar-thumb {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .tools:hover::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border: 1px solid rgba(0, 0, 0, 0.07);
+  }
+  .setting {
+    position: relative;
+    width: calc(100vw - 235px);
+    height: 100%;
+    // overflow-y: hidden;
+    background: #ffffff;
+    .ant-switch.big {
+      min-width: 60px;
+      height: 28px;
+      line-height: 28px;
+      margin-top: -2px;
+      .ant-switch-inner {
+        font-size: 14px;
+      }
+    }
+    .ant-switch.big::after {
+      width: 24px;
+      height: 24px;
+    }
+    .ant-card-head {
+      min-height: 44px;
+    }
+    .ant-card-head-title {
+      padding: 5px 0;
+      color: #1890ff;
+    }
+    .ant-card-extra {
+      padding: 5px 0;
+      button {
+        margin-left: 20px;
+      }
+    }
+    .ant-card-body {
+      position: relative;
+      padding: 0 0 40px;
+
+      .search-list {
+        padding: 1px 24px 20px;
+        min-height: 87px;
+        border-bottom: 1px solid #d9d9d9;
+        > .ant-row {
+          min-height: 65px;
+        }
+        .ant-row .ant-col-6 {
+          padding: 0 12px!important;
+        }
+        .ant-row.ant-form-item .ant-col {
+          padding: 0;
+        }
+        .page-card {
+          position: relative;
+          background: #ffffff;
+          border-radius: 2px;
+          padding-top: 15px;
+          .ant-form-item {
+            cursor: move;
+            display: flex;
+            margin-bottom: 0px;
+            .ant-form-item-label {
+              width: 100px;
+              height: 40px;
+              label {
+                width: 100%;
+                cursor: move;
+                overflow: hidden;
+                display: inline-block;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
+            }
+            .ant-form-item-control-wrapper {
+              flex: 1 1;
+              .ant-select {
+                width: 100%;
+                margin-top: 4px;
+              }
+              .ant-calendar-picker {
+                margin-top: 4px;
+              }
+              .input-mask {
+                position: absolute;
+                top: 0;
+                left: 0;
+                right: 0;
+                bottom: 0;
+                opacity: 0;
+                z-index: 2;
+              }
+              .data-range .ant-calendar-picker-input {
+                padding: 4px 20px 4px 5px;
+                font-size: 13px;
+              }
+            }
+          }
+          .edit {
+            position: absolute;
+            left: 0;
+            top: 5px;
+            color: #1890ff;
+            cursor: pointer;
+            display: none;
+          }
+          .edit.close {
+            left: 20px;
+            color: #ff4d4f;
+          }
+        }
+        .page-card:hover {
+          .edit {
+            display: inline-block;
+          }
+        }
+        .ant-calendar-picker {
+          min-width: 100px!important;
+          width: 100%;
+        }
+      }
+      .action-list {
+        padding: 0px 20px 15px;
+        min-height: 82px;
+        > .ant-row {
+          min-height: 67px;
+        }
+        .page-card {
+          display: inline-block;
+          margin: 0px 0px 0px 0px;
+          padding: 15px 10px 0 0;
+          position: relative;
+          div {
+            cursor: move;
+          }
+          .edit {
+            position: absolute;
+            left: 0;
+            top: 0px;
+            color: #1890ff;
+            cursor: pointer;
+            display: none;
+          }
+          .edit.close {
+            left: 40px;
+            color: #ff4d4f;
+          }
+          .edit.copy {
+            left: 20px;
+            color: #26C281;
+          }
+          .edit.profile {
+            left: 60px;
+            color: purple;
+          }
+          button {
+            cursor: move;
+            min-width: 65px;
+            .anticon-table {
+              font-size: 10px;
+              position: absolute;
+              right: 1px;
+              bottom: 0px;
+            }
+          }
+        }
+        .page-card:hover {
+          .edit {
+            display: inline-block;
+          }
+        }
+      }
+      .column-list {
+        position: relative;
+        padding: 0px 20px;
+        .ant-switch {
+          position: absolute;
+          right: 20px;
+          top: -10px;
+        }
+        > .ant-row {
+          background: #fafafa;
+          border-radius: 4px;
+          min-height: 47px;
+          border: 1px solid #e8e8e8;
+          .column-box {
+            display: flex;
+          }
+          .column-box:not(:first-child) {
+            border-top: 1px solid #e8e8e8;
+          }
+          .page-card {
+            position: relative;
+            padding: 0px;
+            min-height: 45px;
+            > div {
+              padding: 12px 0px 0px;
+              cursor: move;
+              height: 100%;
+              .ant-table-column-sorters {
+                padding: 0px 8px 12px;
+              }
+              .ant-table-column-fields {
+                padding: 0px 8px 5px;
+              }
+            }
+            .ant-table-column-sorter {
+              position: relative;
+              display: inline-block;
+              width: 24px;
+              font-size: 12px;
+              color: #bfbfbf;
+              .anticon-caret-up {
+                position: relative;
+                left: 10px;
+                top: -3px;
+              }
+              .anticon-caret-down {
+                position: relative;
+                left: -2px;
+                top: 3px;
+              }
+            }
+            .edit {
+              position: absolute;
+              left: 0;
+              top: 0px;
+              color: #1890ff;
+              cursor: pointer;
+              display: none;
+            }
+            .edit.close {
+              left: 20px;
+              color: #ff4d4f;
+            }
+            .ant-checkbox-inner {
+              margin-top: 14px;
+              margin-left: calc(50% - 8px);
+            }
+          }
+          .page-card:hover {
+            .edit {
+              display: inline-block;
+            }
+          }
+          .page-card:not(:last-child) {
+            border-right: 1px solid #e8e8e8;
+          }
+        }
+      }
+      .tab-list {
+        position: relative;
+        padding: 30px 20px 0px;
+        .ant-switch {
+          position: absolute;
+          right: 20px;
+          top: 20px;
+        }
+        > .ant-row {
+          min-height: 47px;
+          .page-card {
+            position: relative;
+            padding: 0px;
+            > div {
+              padding: 12px 0px 0px;
+              cursor: move;
+            }
+          }
+          .ant-tabs-tab {
+            .edit {
+              position: absolute;
+              left: 0;
+              top: 0px;
+              color: #1890ff;
+              cursor: pointer;
+              display: none;
+            }
+            .edit.close {
+              left: 20px;
+              color: #ff4d4f;
+            }
+          }
+          .ant-tabs-bar {
+            min-height: 55px;
+          }
+          .ant-tabs-tab:hover {
+            .edit {
+              display: inline-block;
+            }
+          }
+          .ant-tabs-content {
+            .ant-tabs-tabpane img {
+              width: 100%;
+            }
+          }
+        }
+        > .anticon-question-circle {
+          position: absolute;
+          left: 5px;
+          top: 20px;
+        }
+        > .anticon-plus {
+          position: absolute;
+          font-size: 24px;
+          right: 25px;
+          top: 50px;
+          z-index: 1;
+          cursor: pointer;
+        }
+        > .anticon-delete {
+          position: absolute;
+          font-size: 24px;
+          right: 25px;
+          top: 50px;
+          z-index: 1;
+          cursor: pointer;
+        }
+        .ant-tabs-nav-container-scrolling {
+          margin-right: 50px;
+        }
+      }
+      > .anticon-setting {
+        position: absolute;
+        font-size: 18px;
+        right: 5px;
+        top: 10px;
+        padding: 10px;
+        z-index: 1;
+      }
+    }
+    .anticon-question-circle {
+      color: #c49f47;
+      position: relative;
+      left: -15px;
+      top: 5px;
+    }
+  }
+  .setting {
+    overflow-y: scroll;
+  }
+  .setting::-webkit-scrollbar {
+    width: 7px;
+  }
+  .setting::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+    display: none;
+  }
+  .setting::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
+  .setting:hover::-webkit-scrollbar-thumb {
+    display: block;
+  }
+  .ant-spin {
+    position: absolute;
+    margin-left: calc(50vw - 22px);
+    margin-top: 30vh;
+  }
+}
+
+.common-table-fields-modal {
+  .ant-modal {
+    top: 50px;
+    padding-bottom: 5px;
+    .ant-modal-body {
+      max-height: calc(100vh - 190px);
+      overflow-y: auto;
+      .ant-empty {
+        margin: 15vh 8px;
+      }
+    }
+    .ant-modal-body::-webkit-scrollbar {
+      width: 7px;
+    }
+    .ant-modal-body::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+      background: rgba(0, 0, 0, 0.13);
+    }
+    .ant-modal-body::-webkit-scrollbar-track {
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+      border-radius: 3px;
+      border: 1px solid rgba(0, 0, 0, 0.07);
+      background: rgba(0, 0, 0, 0);
+    }
+  }
+}
diff --git a/src/templates/modalviewconfig/settingform/index.jsx b/src/templates/modalviewconfig/settingform/index.jsx
new file mode 100644
index 0000000..243ed97
--- /dev/null
+++ b/src/templates/modalviewconfig/settingform/index.jsx
@@ -0,0 +1,312 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon, notification } from 'antd'
+import './index.scss'
+
+const { TextArea } = Input
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    menu: PropTypes.object,
+    data: PropTypes.object,
+    config: PropTypes.object,
+    columns: PropTypes.array,
+    usefulFields: PropTypes.array
+  }
+
+  state = {
+    interType: this.props.data.interType || 'inner',
+    columns: this.props.columns.filter(item => item.field && item.type !== 'colspan'),
+    currentTabs: null,
+    selectTabs: []
+  }
+
+  UNSAFE_componentWillMount() {
+    const { config, data } = this.props
+    let _tabs = []
+    let _select = []
+    let _tabMap = new Map()
+
+    config.tabgroups.forEach(groupname => {
+      config[groupname].forEach(tab => {
+        if (tab.origin) return
+
+        _tabs.push(tab)
+        _tabMap.set(tab.uuid, true)
+      })
+    })
+
+    data.subtabs && data.subtabs.forEach(tabId => {
+      if (_tabMap.has(tabId)) {
+        _select.push(tabId)
+      }
+    })
+
+    this.setState({
+      currentTabs: _tabs,
+      selectTabs: _select
+    })
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          values.actionfixed = values.actionfixed === 'true'
+          values.columnfixed = values.columnfixed === 'true'
+
+          if (values.interType === 'inner' && !values.innerFunc && !values.dataresource) {
+            notification.warning({
+              top: 92,
+              message: '璇疯嚜瀹氫箟鍑芥暟鎴栧~鍐欐暟鎹簮锛�',
+              duration: 10
+            })
+          } else {
+            resolve(values)
+          }
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  onChange = (e) => {
+    this.setState({
+      interType: e.target.value
+    })
+  }
+
+  selectChange = (val) => {
+    // let _order = this.props.form.getFieldValue('order')
+    this.props.form.setFieldsValue({
+      order: `${val} desc`
+    })
+  }
+
+  render() {
+    const { data, dict, menu, usefulFields } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { interType, columns, selectTabs } = this.state
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    let primaryKey = data.primaryKey
+    if (primaryKey) {
+      let field = columns.filter(column => column.field === primaryKey)
+      if (field.length !== 1) {
+        primaryKey = ''
+      }
+    }
+    if (!primaryKey && columns.length === 0) {
+      primaryKey = 'ID'
+    }
+
+    let str = '^(' + usefulFields.join('|') + ')'
+    let _patten = new RegExp(str + '[0-9a-zA-Z_]*$', 'g')
+
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form commontable-setting-form" id="commontable-setting-form">
+        <Row gutter={24}>
+          <Col span={12}>
+            <Form.Item label="琛ㄥ悕">
+              {getFieldDecorator('tableName', {
+                initialValue: data.tableName,
+                rules: [
+                  {
+                    required: true,
+                    message: dict['form.required.input'] + '琛ㄥ悕!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="琛ㄦ牸灞炴��">
+              {getFieldDecorator('tableType', {
+                initialValue: data.tableType
+              })(
+                <Select
+                  getPopupContainer={() => document.getElementById('commontable-setting-form')}
+                >
+                  <Select.Option value="">涓嶅彲閫�</Select.Option>
+                  <Select.Option value="radio">鍗曢��</Select.Option>
+                  <Select.Option value="checkbox">澶氶��</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={dict['header.form.intertype']}>
+              {getFieldDecorator('interType', {
+                initialValue: data.interType || 'inner'
+              })(
+                <Radio.Group onChange={this.onChange}>
+                  <Radio value="inner">{dict['header.form.interface.inner']}</Radio>
+                  <Radio value="outer">{dict['header.form.interface.outer']}</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          {interType === 'outer' ? <Col span={12}>
+            <Form.Item label={dict['header.form.interface']}>
+              {getFieldDecorator('interface', {
+                initialValue: data.interface || '',
+                rules: [
+                  {
+                    required: true,
+                    message: dict['form.required.input'] + dict['header.form.interface'] + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col> : null}
+          {interType === 'outer' ? <Col span={12}>
+            <Form.Item label={dict['header.form.outerFunc']}>
+              {getFieldDecorator('outerFunc', {
+                initialValue: data.outerFunc || ''
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col> : null}
+          {interType !== 'outer' ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" overlayClassName="middle" title={`鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠�${usefulFields.join(', ')}绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愩�俙}>
+                <Icon type="question-circle" />
+                {dict['header.form.innerFunc']}
+              </Tooltip>
+            }>
+              {getFieldDecorator('innerFunc', {
+                initialValue: data.innerFunc || '',
+                rules: [
+                  {
+                    pattern: _patten,
+                    message: '鍚嶇О鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶅拰涓嬪垝绾匡紝涓斾互鎸囧畾瀛楃寮�濮嬨��'
+                  }, {
+                    max: 50,
+                    message: '鍐呴儴鍑芥暟鍚嶇О涓嶈秴杩�50涓瓧绗︺��'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col> : null}
+          {interType !== 'outer' ? <Col span={24}>
+            <Form.Item help={'鏁版嵁ID锛�' + menu.MenuID} label={
+              <Tooltip placement="topLeft" title="浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愶紝鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�">
+                <Icon type="question-circle" />
+                {'鏁版嵁婧�'}
+              </Tooltip>
+            } className="textarea">
+              {getFieldDecorator('dataresource', {
+                initialValue: data.dataresource
+              })(<TextArea rows={4} />)}
+            </Form.Item>
+          </Col> : null}
+          <Col span={12}>
+            <Form.Item label="鍥哄畾鎸夐挳">
+              {getFieldDecorator('actionfixed', {
+                initialValue: data.actionfixed ? 'true' : 'false'
+              })(
+                <Select>
+                  <Select.Option value="true">鏄�</Select.Option>
+                  <Select.Option value="false">鍚�</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="鍥哄畾鍒�">
+              {getFieldDecorator('columnfixed', {
+                initialValue: data.columnfixed ? 'true' : 'false'
+              })(
+                <Select>
+                  <Select.Option value="true">鏄�</Select.Option>
+                  <Select.Option value="false">鍚�</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="涓婚敭">
+              {getFieldDecorator('primaryKey', {
+                initialValue: primaryKey
+              })(
+                <Select
+                  getPopupContainer={() => document.getElementById('commontable-setting-form')}
+                  onChange={this.selectChange}
+                >
+                  <Select.Option key='unset' value="">涓嶈缃�</Select.Option>
+                  {columns.length === 0 ?
+                    <Select.Option key='id' value="ID">ID</Select.Option> : null
+                  }
+                  {columns.map((option, index) =>
+                    <Select.Option id={option.uuid} title={option.label} key={index} value={option.field}>{option.label}</Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="榛樿鎺掑簭">
+              {getFieldDecorator('order', {
+                initialValue: data.order || (primaryKey ? primaryKey + ' desc' : ''),
+                rules: [
+                  {
+                    required: true,
+                    message: dict['form.required.input'] + '榛樿鎺掑簭瀛楁!'
+                  }
+                ]
+              })(<Input placeholder="ID asc, UID desc" autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label="鍒濆鍖�">
+              {getFieldDecorator('onload', {
+                initialValue: data.onload || 'true'
+              })(
+                <Select>
+                  <Select.Option value="true">鍔犺浇鏁版嵁</Select.Option>
+                  <Select.Option value="false">涓嶅姞杞芥暟鎹�</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="涓昏〃鍙�夊彇鍏宠仈鏍囩锛屾爣绛惧叧鑱斿悗锛屼富琛ㄦ暟鎹垏鎹㈡椂锛屼笅绾ф爣绛句細璺熼殢涓昏〃涓婚敭鍊煎彉鍖栥��">
+                <Icon type="question-circle" />
+                {'涓嬬骇鏍囩'}
+              </Tooltip>
+            }>
+              {getFieldDecorator('subtabs', {
+                initialValue: selectTabs
+              })(
+                <Select
+                  mode="multiple"
+                  style={{ width: '100%' }}
+                  placeholder="Please select"
+                >
+                  {this.state.currentTabs.map((option, index) =>
+                    <Select.Option id={option.uuid} title={option.label} key={index} value={option.uuid}>{option.label}</Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/settingform/index.scss b/src/templates/modalviewconfig/settingform/index.scss
new file mode 100644
index 0000000..cd1a9f6
--- /dev/null
+++ b/src/templates/modalviewconfig/settingform/index.scss
@@ -0,0 +1,14 @@
+.ant-advanced-search-form.commontable-setting-form {
+  .textarea {
+    .ant-form-item-label {
+      width: 16.3%;
+    }
+    .ant-form-item-control-wrapper {
+      width: 83.33333333%;
+    }
+  }
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+}
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/source.jsx b/src/templates/modalviewconfig/source.jsx
new file mode 100644
index 0000000..c0240de
--- /dev/null
+++ b/src/templates/modalviewconfig/source.jsx
@@ -0,0 +1,375 @@
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/comtable.js'
+import enUS from '@/locales/en-US/comtable.js'
+
+const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
+
+class CommonTableBaseData {
+  baseConfig = {
+    type: 'system',
+    enabled: false,
+    setting: {
+      actionfixed: false,
+      columnfixed: false,
+      tableName: '',
+      tableType: 'checkbox',
+      primaryKey: '',
+      order: '',
+      dataresource: '',
+      interType: 'inner',
+      innerFunc: '',
+      interface: '',
+      outerFunc: '',
+      onload: 'true',
+      subtabs: []
+    },
+    tables: [],
+    search: [
+      {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'label',
+        field: '',
+        initval: '',
+        type: 'text',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'like',
+        display: 'dropdown'
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'label',
+        field: '',
+        initval: '',
+        type: 'select',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'equal',
+        display: 'dropdown'
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'label',
+        field: '',
+        initval: '',
+        type: 'date',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'greater',
+        display: 'dropdown'
+      }
+    ],
+    action: [
+      {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'add',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        method: 'POST',
+        outerFunc: '',
+        sql: '',
+        sqlType: '',
+        callbackFunc: '',
+        Ot: 'notRequired',
+        position: 'toolbar',
+        execSuccess: 'grid',
+        execError: 'never',
+        errorTime: 15,
+        OpenType: 'pop',
+        pageTemplate: '',
+        url: '',
+        icon: 'plus',
+        class: 'green',
+        verify: null
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'update',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        method: 'POST',
+        outerFunc: '',
+        sql: '',
+        sqlType: '',
+        callbackFunc: '',
+        Ot: 'requiredSgl',
+        position: 'grid',
+        execSuccess: 'grid',
+        execError: 'never',
+        errorTime: 15,
+        OpenType: 'pop',
+        pageTemplate: '',
+        url: '',
+        icon: 'form',
+        class: 'purple',
+        verify: null
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        label: 'delete',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        method: 'POST',
+        outerFunc: '',
+        sql: '',
+        sqlType: '',
+        callbackFunc: '',
+        Ot: 'required',
+        position: 'toolbar',
+        execSuccess: 'grid',
+        execError: 'never',
+        errorTime: 15,
+        OpenType: 'prompt',
+        pageTemplate: '',
+        url: '',
+        icon: 'delete',
+        class: 'red',
+        verify: null
+      }
+    ],
+    columns: [
+      {
+        origin: true,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'label',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'label',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'label',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'label',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }
+    ],
+    gridBtn: {
+      display: false,
+      Align: 'center',
+      IsSort: 'false',
+      uuid: Utils.getuuid(),
+      label: CommonDict['header.form.column.action'],
+      type: 'action',
+      style: 'button',
+      show: 'horizontal',
+      Width: 120
+    },
+    tabs: [
+      {
+        origin: true,          // 鏄惁涓虹ず渚�
+        groupId: 'tabs',
+        uuid: Utils.getuuid(),
+        label: 'tab1',
+        icon: '',
+        type: 'SubTable',
+        linkTab: '',
+        subtabs: [],
+        supMenu: ''
+      },
+      {
+        origin: true,
+        groupId: 'tabs',
+        uuid: Utils.getuuid(),
+        label: 'tab2',
+        icon: '',
+        type: 'SubTable',
+        linkTab: '',
+        subtabs: [],
+        supMenu: ''
+      }
+    ],
+    tabgroups: ['tabs']
+  }
+
+  searchItems = [
+    {
+      type: 'search',
+      label: '鏂囨湰妗�',
+      subType: 'text',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '涓嬫媺妗�',
+      subType: 'select',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙澶╋級',
+      subType: 'date',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙鍛級',
+      subType: 'dateweek',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙鏈堬級',
+      subType: 'datemonth',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙鍖洪棿锛�',
+      subType: 'daterange',
+      url: ''
+    }
+  ]
+
+  actionItems = [
+    {
+      type: 'action',
+      label: CommonDict['header.form.popform'],
+      subType: 'pop',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.prompt'],
+      subType: 'prompt',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.exec'],
+      subType: 'exec',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.excelIn'],
+      subType: 'excelIn',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.excelOut'],
+      subType: 'excelOut',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.popview'],
+      subType: 'popview',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.tab'],
+      subType: 'tab',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.blank'],
+      subType: 'blank',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.newpage.inner'],
+      subType: 'innerpage',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.newpage.outer'],
+      subType: 'outerpage',
+      url: ''
+    }
+  ]
+
+  columnItems = [
+    {
+      type: 'columns',
+      label: CommonDict['header.form.text'],
+      subType: 'text',
+      url: ''
+    },
+    {
+      type: 'columns',
+      label: CommonDict['header.form.number'],
+      subType: 'number',
+      url: ''
+    },
+    {
+      type: 'columns',
+      label: CommonDict['header.form.picture'],
+      subType: 'picture',
+      url: ''
+    },
+    {
+      type: 'columns',
+      label: CommonDict['header.form.colspan'],
+      subType: 'colspan',
+      url: ''
+    }
+  ]
+
+  tabItems = [
+    {
+      type: 'tabs',
+      label: CommonDict['header.menu.tab.subtable'],
+      subType: 'SubTable',
+    }
+  ]
+}
+
+export default new CommonTableBaseData()
diff --git a/src/templates/modalviewconfig/tabdragelement/card.jsx b/src/templates/modalviewconfig/tabdragelement/card.jsx
new file mode 100644
index 0000000..2437661
--- /dev/null
+++ b/src/templates/modalviewconfig/tabdragelement/card.jsx
@@ -0,0 +1,41 @@
+import React from 'react'
+import { useDrag, useDrop } from 'react-dnd'
+import { Icon } from 'antd'
+import './index.scss'
+
+const Card = ({ id, type, card, moveCard, findCard, editCard, delCard, hasDrop }) => {
+  const originalIndex = findCard(id).index
+  const [{ isDragging }, drag] = useDrag({
+    item: { type: type, id, originalIndex },
+    collect: monitor => ({
+      isDragging: monitor.isDragging(),
+    }),
+  })
+  const [, drop] = useDrop({
+    accept: type,
+    canDrop: () => true,
+    drop: (item) => {
+      if (!item.hasOwnProperty('originalIndex')) {
+        hasDrop(card)
+      }
+    },
+    hover({ id: draggedId }) {
+      if (!draggedId) return
+      if (draggedId !== id) {
+        const { index: overIndex } = findCard(id)
+        moveCard(draggedId, overIndex)
+      }
+    },
+  })
+  const opacity = isDragging ? 0 : 1
+
+  return (
+    <div className="page-card" style={{ opacity: opacity}}>
+      <div ref={node => drag(drop(node))}>
+        {card.icon ? <Icon type={card.icon} /> : null}
+        {card.label}
+      </div>
+    </div>
+  )
+}
+export default Card
diff --git a/src/templates/modalviewconfig/tabdragelement/index.jsx b/src/templates/modalviewconfig/tabdragelement/index.jsx
new file mode 100644
index 0000000..5f50bde
--- /dev/null
+++ b/src/templates/modalviewconfig/tabdragelement/index.jsx
@@ -0,0 +1,114 @@
+import React, { useState } from 'react'
+import { useDrop } from 'react-dnd'
+import update from 'immutability-helper'
+import { Tabs, Icon } from 'antd'
+import Utils from '@/utils/utils.js'
+import Card from './card'
+import './index.scss'
+
+const { TabPane } = Tabs
+
+const Container = ({list, type, groupId, placeholder, handleList, handleMenu, deleteMenu }) => {
+  let target = null
+  const [cards, setCards] = useState(list)
+  const moveCard = (id, atIndex) => {
+    const { card, index } = findCard(id)
+
+    if (!card) return
+
+    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
+    setCards(_cards)
+    handleList(type, _cards)
+  }
+
+  const findCard = id => {
+    const card = cards.filter(c => `${c.uuid}` === id)[0]
+    return {
+      card,
+      index: cards.indexOf(card),
+    }
+  }
+
+  const hasDrop = (item) => {
+    target = item
+  }
+
+  const [, drop] = useDrop({
+    accept: type,
+    drop(item) {
+      if (item.hasOwnProperty('originalIndex')) {
+        return
+      }
+
+      let newcard = {}
+      
+      newcard.uuid = Utils.getuuid()
+      newcard.label = 'tab'
+      newcard.icon = ''
+      newcard.type = item.subType
+      newcard.linkTab = Utils.getuuid()
+      newcard.subtabs = []
+      newcard.supMenu = ''
+      newcard.groupId = groupId
+      
+      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
+      if (target) {
+        targetId = target.uuid
+      }
+
+      const { index: overIndex } = findCard(`${targetId}`)
+      let targetIndex = overIndex
+      // if (!target) {
+      targetIndex++
+      // }
+      // if (targetIndex < 0) {
+      //   targetIndex = 0
+      // }
+
+      const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
+      setCards(_cards)
+      handleList(type, _cards, newcard)
+      target = null
+    }
+  })
+  
+  const edit = (card) => {
+    handleMenu(card)
+  }
+  
+  const del = (card) => {
+    deleteMenu({card: card, type: type})
+  }
+
+  return (
+    <div ref={drop} className="ant-row maintable-tab-list">
+      <Tabs defaultActiveKey="0">
+        {cards.map((card, index) => (
+          <TabPane tab={
+            <div key={card.uuid}>
+              <Card
+                key={card.uuid}
+                id={`${card.uuid}`}
+                type={type}
+                card={card}
+                moveCard={moveCard}
+                findCard={findCard}
+                hasDrop={hasDrop}
+              />
+              <Icon className="edit" type="edit" onClick={() => edit(card)} />
+              <Icon className="edit close" type="close" onClick={() => del(card)} />
+            </div>
+          } key={`${index}`}>
+            銆妠card.label}銆嬫爣绛惧唴瀹�
+          </TabPane>
+        ))}
+      </Tabs>
+      {cards.length === 0 ?
+        <div className="commontab-drawarea-placeholder">
+          {placeholder}
+        </div> : null
+      }
+    </div>
+  )
+}
+export default Container
diff --git a/src/templates/modalviewconfig/tabdragelement/index.scss b/src/templates/modalviewconfig/tabdragelement/index.scss
new file mode 100644
index 0000000..56fbd3b
--- /dev/null
+++ b/src/templates/modalviewconfig/tabdragelement/index.scss
@@ -0,0 +1,21 @@
+.common-source-item {
+  display: block;
+  box-shadow: 0px 0px 2px #bcbcbc;
+  padding: 0.4rem 0.7rem;
+  background-color: white;
+  margin: 0px 0px 10px;
+  cursor: move;
+  border-radius: 4px;
+}
+.maintable-tab-list {
+  .ant-tabs-content {
+    text-align: center;
+    color: #bcbcbc;
+  }
+  .commontab-drawarea-placeholder {
+    position: absolute;
+    top: 25px;
+    left: calc(50% - 50px);
+    color: #bcbcbc;
+  }
+}
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/tabform/index.jsx b/src/templates/modalviewconfig/tabform/index.jsx
new file mode 100644
index 0000000..1d598b0
--- /dev/null
+++ b/src/templates/modalviewconfig/tabform/index.jsx
@@ -0,0 +1,227 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, Icon, Tooltip } from 'antd'
+import Utils from '@/utils/utils.js'
+import './index.scss'
+
+
+class MainTab extends Component {
+  static propTpyes = {
+    tabs: PropTypes.array,   // 绫诲瀷
+    type: PropTypes.string,  // 绫诲瀷
+    dict: PropTypes.object,  // 瀛楀吀椤�
+    formlist: PropTypes.any, // 琛ㄥ崟
+    card: PropTypes.object   // 鏍囩椤典俊鎭�
+  }
+
+  state = {
+    formlist: null // 琛ㄥ崟
+  }
+
+  /**
+   * @description 琛ㄥ崟棰勫鐞�
+   */
+  UNSAFE_componentWillMount () {
+    const { formlist } = this.props
+
+    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
+    let _initval = formlist.filter(cell => cell.key === 'linkTab')[0].initVal
+
+    let _tabs = this.props.tabs.filter(tab => tab.type === type)
+    let initTab = _tabs.filter(tab => tab.uuid === _initval)[0]
+
+    this.setState({
+      formlist: formlist.map(item => {
+        if (item.key === 'linkTab') {
+          item.options = [
+            {
+              value: '',
+              text: '鏂板缓'
+            },
+            ..._tabs
+          ]
+          if (!initTab) {
+            item.initVal = ''
+          }
+        }
+
+        return item
+      })
+    })
+  }
+
+  /**
+   * @description 鏍囩椤电被鍨嬪垏鎹�
+   */
+  openTypeChange = (key, value) => {
+    const { formlist } = this.state
+
+    if (key === 'type') {
+      let _tabs = this.props.tabs.filter(tab => tab.type === value)
+
+      this.setState({
+        formlist: formlist.map(item => {
+          if (item.key === 'linkTab') {
+            item.options = [
+              {
+                value: '',
+                text: '鏂板缓'
+              },
+              ..._tabs
+            ]
+            item.initVal = ''
+            item.hidden = true
+          }
+          return item
+        })
+      }, () => {
+        this.setState({
+          formlist: this.state.formlist.map(item => {
+            if (item.key === 'linkTab') {
+              item.hidden = false
+            }
+            return item
+          })
+        })
+      })
+
+      // this.setState({
+      //   formlist: this.state.formlist.map(form => {
+      //     return form
+      //   })
+      // }, () => {
+      //   this.setState({
+      //     formlist: this.state.formlist.map(form => {
+      //       return form
+      //     })
+      //   })
+      // })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+    
+    this.state.formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.openTypeChange(item.key, value)}}
+                >
+                  {item.options.map((option, i) =>
+                    <Select.Option id={'mk' + i} title={option.text} key={'mk' + i} value={option.value}>
+                      {item.key === 'icon' && i !== 0 ? <Icon type={option.text} /> : option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'mutilselect') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鏍囩鍙叧鑱斾笅绾ф爣绛撅紝涓嬬骇鏍囩鍙�夎寖鍥达細鐩搁偦鐨勪笅渚ф爣绛剧粍涓湭琚悓绾ф垨涓昏〃鍏宠仈鐨勬爣绛俱��">
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip>
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal
+              })(
+                <Select
+                  mode="multiple"
+                  style={{ width: '100%' }}
+                  placeholder="Please select"
+                >
+                  {item.options.map((option, index) =>
+                    <Select.Option id={option.uuid} title={option.label} key={index} value={option.uuid}>{option.label}</Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+
+          values.uuid = this.props.card.uuid
+          values.groupId = this.props.card.groupId
+
+          if (!values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d
+            values.linkTab = Utils.getuuid()
+          }
+
+          resolve({
+            type: this.props.type,
+            values
+          })
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form commontable-tab-form">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainTab)
\ No newline at end of file
diff --git a/src/templates/modalviewconfig/tabform/index.scss b/src/templates/modalviewconfig/tabform/index.scss
new file mode 100644
index 0000000..930f1a5
--- /dev/null
+++ b/src/templates/modalviewconfig/tabform/index.scss
@@ -0,0 +1,7 @@
+.ant-advanced-search-form.commontable-tab-form {
+  min-height: 180px;
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+}
\ No newline at end of file
diff --git a/src/templates/tableshare/verifycard/billcodeform/index.jsx b/src/templates/tableshare/verifycard/billcodeform/index.jsx
index 34674b5..4ea880c 100644
--- a/src/templates/tableshare/verifycard/billcodeform/index.jsx
+++ b/src/templates/tableshare/verifycard/billcodeform/index.jsx
@@ -1,30 +1,54 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Button, notification } from 'antd'
+import { Form, Row, Col, Select, Button, InputNumber } from 'antd'
 import './index.scss'
 
 
 class UniqueForm extends Component {
   static propTpyes = {
     dict: PropTypes.object,  // 瀛楀吀椤�
+    fields: PropTypes.array,  // 琛ㄥ崟
+    columns: PropTypes.array,  // 琛ㄥ崟
     modular: PropTypes.array,  // 琛ㄥ崟
     modularDetail: PropTypes.array,  // 琛ㄥ崟
-    orderChange: PropTypes.func,  // 琛ㄥ崟
-    orderCheck: PropTypes.func  // 琛ㄥ崟
+    orderChange: PropTypes.func  // 琛ㄥ崟
   }
 
   state = {
     editItem: null,
-    modularDetail: []
+    modularDetail: [],
+    funFields: [],
+    billFields: [],
+    type: '1'
   }
 
   UNSAFE_componentWillMount() {
+    let _modularDetail = []
+    let _billFields = []
     if (this.props.modular.length > 0) {
-      this.setState({
-        modularDetail: this.props.modularDetail.filter(item => item.BID === this.props.modular[0].ID)
-      })
+      _modularDetail = this.props.modularDetail.filter(item => item.BID === this.props.modular[0].ID)
     }
+
+    let fieldMap = new Map()
+    this.props.fields.forEach(_field => {
+      if (_field.type === 'text' && !fieldMap.has(_field.field)) {
+        _billFields.push(_field)
+        fieldMap.set(_field.field, true)
+      }
+    })
+    this.props.columns.forEach(_field => {
+      if (_field.type === 'text' && !fieldMap.has(_field.field)) {
+        _billFields.push(_field)
+        fieldMap.set(_field.field, true)
+      }
+    })
+
+    this.setState({
+      modularDetail: _modularDetail,
+      funFields: this.props.fields.filter(field => field.type === 'funcvar'),
+      billFields: _billFields
+    })
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
@@ -34,34 +58,41 @@
       this.setState({
         modularDetail: _detail
       })
-
-      this.props.form.setFieldsValue({
-        ModularCode: nextProps.modular[0].ID,
-        ModularDetailCode: _detail[0] ? _detail[0].ModularDetailCode : ''
-      })
     }
   }
 
   edit = (record) => {
-    let _detail = this.props.modularDetail.filter(item => item.BID === record.ModularCode)
-    let _modularDetailCode = ''
+    if (record.TypeCharOne === 'Y' || record.TypeCharOne === 'n') {
+      let _detail = this.props.modularDetail.filter(item => item.BID === record.ModularCode)
+      let _modularDetailCode = ''
 
-    if (_detail.filter(item => item.ModularDetailCode === record.ModularDetailCode).length > 0) {
-      _modularDetailCode = record.ModularDetailCode
+      if (_detail.filter(item => item.ModularDetailCode === record.ModularDetailCode).length > 0) {
+        _modularDetailCode = record.ModularDetailCode
+      }
+
+      this.setState({
+        type: '2',
+        editItem: record,
+        modularDetail: _detail
+      })
+      this.props.form.setFieldsValue({
+        field: record.field,
+        TypeCharOne: record.TypeCharOne,
+        ModularCode: record.ModularCode,
+        ModularDetailCode: _modularDetailCode,
+      })
+    } else {
+      this.setState({
+        type: '1',
+        editItem: record,
+      })
+      this.props.form.setFieldsValue({
+        field: record.field,
+        TypeCharOne: record.TypeCharOne,
+        Type: record.Type,
+        linkField: record.linkField,
+      })
     }
-
-    this.setState({
-      editItem: record,
-      modularDetail: _detail
-    })
-    this.props.form.setFieldsValue({
-      field: record.field,
-      TypeCharOne: record.TypeCharOne,
-      ModularCode: record.ModularCode,
-      ModularDetailCode: _modularDetailCode,
-      errmsg: record.errmsg,
-      errorCode: record.errorCode
-    })
   }
 
   voucherChange = (value) => {
@@ -75,12 +106,28 @@
     })
   }
 
+  TypeCharOneChange = (value) => {
+    if (value === 'Y' || value === 'n') {
+      this.setState({
+        type: '2'
+      })
+    } else {
+      this.setState({
+        type: '1'
+      })
+    }
+  }
 
   handleConfirm = () => {
+    const { funFields, billFields } = this.state
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
         values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        let _funField = funFields.filter(item => item.field === values.field)[0]
+        values.fieldName = _funField ? _funField.label : ''
+
         // 涓�绾ц彍鍗曞�间负20190203125926873D6029A9C511041719420鏃禩ypeCharTwo=TableCode锛屽叾浠栫敤BillCode
         if (values.ModularCode === '20190203125926873D6029A9C511041719420') {
           values.TypeCharTwo = 'TableCode'
@@ -96,22 +143,17 @@
         }
         values.billType = billType[values.TypeCharOne]
 
-        // 璁剧疆鍑瘉绫诲瀷涓枃鍚�
-        let ModularCode = this.props.modular.filter(item => item.ID === values.ModularCode)[0]
-        values.ModularCodeName = ModularCode.NameNO
+        if (values.TypeCharOne === 'Y' || values.TypeCharOne === 'n') {
+          // 璁剧疆鍑瘉绫诲瀷涓枃鍚�
+          let ModularCode = this.props.modular.filter(item => item.ID === values.ModularCode)[0]
+          values.ModularCodeName = ModularCode.NameNO
 
-        // 璁剧疆娴佹按鍙蜂綅鏁�
-        let _detail = this.state.modularDetail.filter(item => item.ModularDetailCode === values.ModularDetailCode)[0]
-        values.Type = _detail.Type
-        let _vaild = this.props.orderCheck(values)
-
-        if (!_vaild) {
-          notification.warning({
-            top: 92,
-            message: '瀛楁鍊间笉鍙噸澶�',
-            duration: 10
-          })
-          return
+          // 璁剧疆娴佹按鍙蜂綅鏁�
+          let _detail = this.state.modularDetail.filter(item => item.ModularDetailCode === values.ModularDetailCode)[0]
+          values.Type = _detail.Type
+        } else {
+          let _billField = billFields.filter(item => item.field === values.linkField)[0]
+          values.linkFieldName = _billField ? _billField.label : ''
         }
 
         this.props.orderChange(values)
@@ -120,7 +162,6 @@
         })
         this.props.form.setFieldsValue({
           field: '',
-          errmsg: ''
         })
       }
     })
@@ -128,6 +169,7 @@
 
   render() {
     const { getFieldDecorator } = this.props.form
+    const { type } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -138,34 +180,35 @@
         sm: { span: 14 }
       }
     }
+
     return (
       <Form {...formItemLayout} className="verify-form">
         <Row gutter={24}>
-          <Col span={6}>
-            <Form.Item label={'瀛楁'}>
+          <Col span={5}>
+            <Form.Item label={'鍑芥暟鍙橀噺'}>
               {getFieldDecorator('field', {
                 initialValue: '',
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.input'] + '瀛楁!'
-                  },
-                  {
-                    pattern: /^[0-9a-zA-Z_]*$/,
-                    message: '鍚嶇О鍙厑璁稿寘鍚暟瀛椼�佸瓧姣嶅拰涓嬪垝绾匡紝涓斾互鎸囧畾瀛楃寮�濮嬨��'
-                  },
-                  {
-                    max: 50,
-                    message: '鍚嶇О涓嶈秴杩�50涓瓧绗︺��'
+                    message: this.props.dict['form.required.input'] + '鍑芥暟鍙橀噺!'
                   }
                 ]
-              })(<Input placeholder="" autoComplete="off" />)}
+              })(
+                <Select>
+                  {this.state.funFields.map(option =>
+                    <Select.Option id={option.uuid} key={option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
             </Form.Item>
           </Col>
-          <Col span={6}>
+          <Col span={5}>
             <Form.Item label={'绫诲瀷'}>
               {getFieldDecorator('TypeCharOne', {
-                initialValue: 'Y',
+                initialValue: 'Lp',
                 rules: [
                   {
                     required: true,
@@ -173,7 +216,7 @@
                   }
                 ]
               })(
-                <Select>
+                <Select onChange={(value) => {this.TypeCharOneChange(value)}}>
                   <Select.Option value="Y"> 鍗曞彿 </Select.Option>
                   <Select.Option value="n"> 缂栫爜 </Select.Option>
                   <Select.Option value="Lp"> 琛屽彿 </Select.Option>
@@ -182,7 +225,41 @@
               )}
             </Form.Item>
           </Col>
-          <Col span={6}>
+          {type === '1' ? <Col span={5}>
+            <Form.Item label={'鍏宠仈瀛楁'}>
+              {getFieldDecorator('linkField', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍏宠仈瀛楁!'
+                  }
+                ]
+              })(
+                <Select>
+                  {this.state.billFields.map(option =>
+                    <Select.Option id={option.uuid} key={option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {type === '1' ? <Col span={5}>
+            <Form.Item label={'浣嶆暟'}>
+              {getFieldDecorator('Type', {
+                initialValue: 4,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '浣嶆暟!'
+                  }
+                ]
+              })(<InputNumber min={1} max={10} precision={0} />)}
+            </Form.Item>
+          </Col> : null}
+          {type === '2' ? <Col span={5}>
             <Form.Item label={'鍑瘉绫诲瀷'}>
               {getFieldDecorator('ModularCode', {
                 initialValue: this.props.modular[0] ? this.props.modular[0].ID : '',
@@ -206,8 +283,8 @@
                 </Select>
               )}
             </Form.Item>
-          </Col>
-          <Col span={6}>
+          </Col> : null}
+          {type === '2' ? <Col span={5}>
             <Form.Item label={'鍑瘉鏍囪瘑'}>
               {getFieldDecorator('ModularDetailCode', {
                 initialValue: this.state.modularDetail[0] ? this.state.modularDetail[0].ModularDetailCode : '',
@@ -230,44 +307,9 @@
                 </Select>
               )}
             </Form.Item>
-          </Col>
-          <Col span={6}>
-            <Form.Item label={'鎻愮ず淇℃伅'}>
-              {getFieldDecorator('errmsg', {
-                initialValue: '',
-                rules: [
-                  {
-                    required: true,
-                    message: this.props.dict['form.required.input'] + '鎻愮ず淇℃伅!'
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={6}>
-            <Form.Item label={'鎶ラ敊缂栫爜'}>
-              {getFieldDecorator('errorCode', {
-                initialValue: 'E',
-                rules: [
-                  {
-                    required: true,
-                    message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!'
-                  }
-                ]
-              })(
-                <Select>
-                  <Select.Option value="E"> E </Select.Option>
-                  <Select.Option value="N"> N </Select.Option>
-                  <Select.Option value="F"> F </Select.Option>
-                  <Select.Option value="NM"> NM </Select.Option>
-                  <Select.Option value="S"> S </Select.Option>
-                  <Select.Option value="-1"> -1 </Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={2}>
-            <Button onClick={this.handleConfirm} type="primary" className="add-row">
+          </Col> : null}
+          <Col span={4} className="add">
+            <Button onClick={this.handleConfirm} type="primary">
               纭畾
             </Button>
           </Col>
diff --git a/src/templates/tableshare/verifycard/customform/index.jsx b/src/templates/tableshare/verifycard/customform/index.jsx
index 656ada3..5571c34 100644
--- a/src/templates/tableshare/verifycard/customform/index.jsx
+++ b/src/templates/tableshare/verifycard/customform/index.jsx
@@ -83,13 +83,13 @@
             </Button>
           </Col>
           <Col span={7}>
-            <Form.Item label={'缁撴灉'}>
+            <Form.Item label={'缁撴灉澶勭悊'}>
               {getFieldDecorator('result', {
                 initialValue: 'true',
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.select'] + '缁撴灉!'
+                    message: this.props.dict['form.required.select'] + '缁撴灉澶勭悊!'
                   }
                 ]
               })(
@@ -131,8 +131,6 @@
                   <Select.Option value="N"> N </Select.Option>
                   <Select.Option value="F"> F </Select.Option>
                   <Select.Option value="NM"> NM </Select.Option>
-                  <Select.Option value="S"> S </Select.Option>
-                  <Select.Option value="-1"> -1 </Select.Option>
                 </Select>
               )}
             </Form.Item>
diff --git a/src/templates/tableshare/verifycard/index.jsx b/src/templates/tableshare/verifycard/index.jsx
index 5fb055e..3a0d6c2 100644
--- a/src/templates/tableshare/verifycard/index.jsx
+++ b/src/templates/tableshare/verifycard/index.jsx
@@ -30,22 +30,17 @@
       {
         title: '瀛楁鍚�',
         dataIndex: 'field',
-        width: '50%'
+        width: '55%'
       },
       {
-        title: '鎻愮ず淇℃伅',
-        dataIndex: 'errmsg',
-        width: '25%'
-      },
-      {
-        title: 'ErrorCode',
+        title: '鎶ラ敊缂栫爜',
         dataIndex: 'errorCode',
-        width: '10%'
+        width: '20%'
       },
       {
         title: '鎿嶄綔',
         align: 'center',
-        width: '15%',
+        width: '25%',
         dataIndex: 'operation',
         render: (text, record) =>
           (<div>
@@ -62,20 +57,20 @@
       {
         title: 'SQL',
         dataIndex: 'sql',
-        width: '40%'
+        width: '50%'
       },
       {
-        title: '缁撴灉',
+        title: '缁撴灉澶勭悊',
         dataIndex: 'resultName',
         width: '10%'
       },
       {
         title: '鎻愮ず淇℃伅',
         dataIndex: 'errmsg',
-        width: '25%'
+        width: '15%'
       },
       {
-        title: 'ErrorCode',
+        title: '鎶ラ敊缂栫爜',
         dataIndex: 'errorCode',
         width: '10%'
       },
@@ -97,38 +92,35 @@
     ],
     orderColumns: [
       {
-        title: '瀛楁',
-        dataIndex: 'field',
-        width: '15%'
+        title: '鍑芥暟鍙橀噺',
+        dataIndex: 'fieldName',
+        width: '15%',
+        render: (text, record) => (`${record.fieldName || ''}(${record.field})`)
       },
       {
         title: '绫诲瀷',
         dataIndex: 'billType',
-        width: '10%',
+        width: '15%',
       },
       {
         title: '鍑瘉绫诲瀷',
         dataIndex: 'ModularCodeName',
-        width: '10%'
+        width: '15%'
       },
       {
         title: '鍑瘉鏍囪瘑',
         dataIndex: 'ModularDetailCode',
-        width: '10%'
+        width: '15%'
       },
       {
-        title: '娴佹按鍙蜂綅鏁�',
+        title: '鍏宠仈瀛楁',
+        dataIndex: 'linkFieldName',
+        width: '15%',
+        render: (text, record) => (record.linkField ? `${record.linkFieldName || ''}(${record.linkField})` : '')
+      },
+      {
+        title: '浣嶆暟',
         dataIndex: 'Type',
-        width: '10%'
-      },
-      {
-        title: '鎻愮ず淇℃伅',
-        dataIndex: 'errmsg',
-        width: '20%'
-      },
-      {
-        title: 'ErrorCode',
-        dataIndex: 'errorCode',
         width: '10%'
       },
       {
@@ -397,17 +389,6 @@
     })
   }
 
-  orderCheck = (values) => {
-    let verify = JSON.parse(JSON.stringify(this.state.verify))
-    let valid = true
-    verify.billcodes.forEach(item => {
-      if (item.uuid !== values.uuid && item.field === values.field) {
-        valid = false
-      }
-    })
-    return valid
-  }
-
   onOptionChange = (e, key) => {
     const { verify } = this.state
     let value = e.target.value
@@ -630,11 +611,12 @@
         </TabPane>
         <TabPane tab="鍗曞彿鐢熸垚" key="4">
           <BillcodeForm
+            fields={fields}
+            columns={this.props.columns}
             dict={this.props.dict}
             modular={orderModular}
             modularDetail={orderModularDetail}
             orderChange={this.orderChange}
-            orderCheck={this.orderCheck}
             wrappedComponentRef={(inst) => this.orderForm = inst}
           />
           <Table
@@ -650,6 +632,7 @@
           <VoucherForm
             dict={this.props.dict}
             voucher={voucher}
+            columns={this.props.columns}
             voucherobj={verify.voucher}
             voucherDetail={voucherDetail}
             voucherChange={this.voucherChange}
diff --git a/src/templates/tableshare/verifycard/uniqueform/index.jsx b/src/templates/tableshare/verifycard/uniqueform/index.jsx
index e9c05ba..9e4b5f1 100644
--- a/src/templates/tableshare/verifycard/uniqueform/index.jsx
+++ b/src/templates/tableshare/verifycard/uniqueform/index.jsx
@@ -1,37 +1,48 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, Button } from 'antd'
+import { Form, Row, Col, Select, Button } from 'antd'
 import './index.scss'
 
 
 class UniqueForm extends Component {
   static propTpyes = {
-    dict: PropTypes.object,  // 瀛楀吀椤�
-    fields: PropTypes.array,  // 琛ㄥ崟
-    uniqueChange: PropTypes.func  // 琛ㄥ崟
+    dict: PropTypes.object,       // 瀛楀吀椤�
+    fields: PropTypes.array,      // 琛ㄥ崟瀛楁
+    uniqueChange: PropTypes.func  // 淇敼鍑芥暟
   }
 
   state = {
-    editItem: null
+    editItem: null // 缂栬緫鍏冪礌
   }
 
   edit = (record) => {
     this.setState({
       editItem: record
     })
+
     this.props.form.setFieldsValue({
       field: record.field.split(','),
-      errmsg: record.errmsg,
       errorCode: record.errorCode
     })
   }
 
 
   handleConfirm = () => {
+    const { fields } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     this.props.form.validateFieldsAndScroll((err, values) => {
       if (!err) {
         values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+        values.fieldlabel = values.field.map(field => {
+          let item = fields.filter(cell => cell.field === field)[0]
+          let label = ''
+          if (item) {
+            label = item.label
+          }
+          return label
+        })
+
+        values.fieldlabel = values.fieldlabel.join(',')
         values.field = values.field.join(',')
 
         this.props.uniqueChange(values)
@@ -40,7 +51,6 @@
         })
         this.props.form.setFieldsValue({
           field: [],
-          errmsg: ''
         })
       }
     })
@@ -59,6 +69,7 @@
         sm: { span: 16 }
       }
     }
+
     return (
       <Form {...formItemLayout} className="verify-form" id="verifycard1">
         <Row gutter={24}>
@@ -84,19 +95,6 @@
             </Form.Item>
           </Col>
           <Col span={6}>
-            <Form.Item label={'鎻愮ず淇℃伅'}>
-              {getFieldDecorator('errmsg', {
-                initialValue: '',
-                rules: [
-                  {
-                    required: true,
-                    message: this.props.dict['form.required.input'] + '鎻愮ず淇℃伅!'
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={6}>
             <Form.Item label={'鎶ラ敊缂栫爜'}>
               {getFieldDecorator('errorCode', {
                 initialValue: 'E',
@@ -112,8 +110,6 @@
                   <Select.Option value="N"> N </Select.Option>
                   <Select.Option value="F"> F </Select.Option>
                   <Select.Option value="NM"> NM </Select.Option>
-                  <Select.Option value="S"> S </Select.Option>
-                  <Select.Option value="-1"> -1 </Select.Option>
                 </Select>
               )}
             </Form.Item>
diff --git a/src/templates/tableshare/verifycard/voucherform/index.jsx b/src/templates/tableshare/verifycard/voucherform/index.jsx
index a661f56..7acdb92 100644
--- a/src/templates/tableshare/verifycard/voucherform/index.jsx
+++ b/src/templates/tableshare/verifycard/voucherform/index.jsx
@@ -1,7 +1,7 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Switch } from 'antd'
+import { Form, Row, Col, Select, Switch } from 'antd'
 import './index.scss'
 
 
@@ -10,33 +10,33 @@
     dict: PropTypes.object,         // 瀛楀吀椤�
     voucherobj: PropTypes.object,   // 鍑瘉淇℃伅
     voucher: PropTypes.array,       // 琛ㄥ崟
+    columns: PropTypes.array,       // 琛ㄥ崟
     voucherDetail: PropTypes.array, // 琛ㄥ崟
-    voucherChange: PropTypes.func  // 琛ㄥ崟
+    voucherChange: PropTypes.func   // 琛ㄥ崟
   }
 
   state = {
     voucher: [],
-    voucherDetail: []
+    voucherDetail: [],
+    columns: []
   }
 
   UNSAFE_componentWillMount() {
+    let _voucher = []
+    let _voucherDetail = []
     if (this.props.voucherobj.BVoucherType && this.props.voucher.length > 0) {
-      let _voucher = this.props.voucher.filter(item => item.TypeCharOne === this.props.voucherobj.BVoucherType)
-      let _voucherDetail = this.props.voucherDetail.filter(item => item.BID === this.props.voucherobj.VoucherType)
-
-      this.setState({
-        voucher: _voucher,
-        voucherDetail: _voucherDetail
-      })
+      _voucher = this.props.voucher.filter(item => item.TypeCharOne === this.props.voucherobj.BVoucherType)
+      _voucherDetail = this.props.voucherDetail.filter(item => item.BID === this.props.voucherobj.VoucherType)
     } else if (this.props.voucher.length > 0) {
-      let _voucher = this.props.voucher.filter(item => item.TypeCharOne === 'MES')
-      let _voucherDetail = this.props.voucherDetail.filter(item => _voucher[0] && item.BID === _voucher[0].ID)
-
-      this.setState({
-        voucher: _voucher,
-        voucherDetail: _voucherDetail
-      })
+      _voucher = this.props.voucher.filter(item => item.TypeCharOne === 'MES')
+      _voucherDetail = this.props.voucherDetail.filter(item => _voucher[0] && item.BID === _voucher[0].ID)
     }
+
+    this.setState({
+      voucher: _voucher,
+      voucherDetail: _voucherDetail,
+      columns: this.props.columns.filter(col => col.type === 'text')
+    })
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
@@ -137,6 +137,7 @@
   render() {
     const { getFieldDecorator } = this.props.form
     const { voucherobj } = this.props
+    const { columns } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -147,6 +148,7 @@
         sm: { span: 14 }
       }
     }
+
     return (
       <Form {...formItemLayout} className="verify-form">
         <Row gutter={24}>
@@ -221,36 +223,26 @@
             </Form.Item>
           </Col>
           <Col span={6}>
-            <Form.Item label={'鎻愮ず淇℃伅'}>
-              {getFieldDecorator('errmsg', {
-                initialValue: voucherobj.errmsg ||'',
+            <Form.Item label={'鍏宠仈瀛楁'}>
+              {getFieldDecorator('linkField', {
+                initialValue: voucherobj.linkField || (columns[0] && columns[0].field) || '',
                 rules: [
                   {
                     required: true,
-                    message: this.props.dict['form.required.input'] + '鎻愮ず淇℃伅!'
-                  }
-                ]
-              })(<Input placeholder="" onChange={this.contentChange} autoComplete="off" />)}
-            </Form.Item>
-          </Col>
-          <Col span={6}>
-            <Form.Item label={'鎶ラ敊缂栫爜'}>
-              {getFieldDecorator('errorCode', {
-                initialValue: voucherobj.errmsg || 'E',
-                rules: [
-                  {
-                    required: true,
-                    message: this.props.dict['form.required.select'] + '鎶ラ敊缂栫爜!'
+                    message: this.props.dict['form.required.input'] + '鍏宠仈瀛楁!'
                   }
                 ]
               })(
-                <Select onChange={this.contentChange}>
-                  <Select.Option value="E"> E </Select.Option>
-                  <Select.Option value="N"> N </Select.Option>
-                  <Select.Option value="F"> F </Select.Option>
-                  <Select.Option value="NM"> NM </Select.Option>
-                  <Select.Option value="S"> S </Select.Option>
-                  <Select.Option value="-1"> -1 </Select.Option>
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={this.contentChange}
+                >
+                  {columns.map((option, index) =>
+                    <Select.Option id={index + option.uuid} key={index + option.uuid} value={option.field}>
+                      {option.label}
+                    </Select.Option>
+                  )}
                 </Select>
               )}
             </Form.Item>
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 28c63dd..2a52009 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -448,41 +448,139 @@
    * @return {String} type   鎵ц绫诲瀷
    * @return {String} table  琛ㄥ悕
    */
-  static getSysDefaultSql (btn, setting, formdata, primaryId) {
-    // let verify = btn.verify
-    let primaryKey = setting.primaryKey || 'id'
-    let _sql = ''
+  static getSysDefaultSql (btn, setting, formdata, primaryId, data) {
+    let verify = btn.verify
+    let _formFieldValue = {}
 
-    // if (verify && verify.accountdate === 'true') {
-    //   _sql += `exec s_FIBVoucherDateCheck @ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT
-    //     if @ErrorCode!=''
-    //     GOTO aaa
-    //     `
-    // }
-    // if (verify && verify.invalid === 'true') {
-    //   _sql += `Declare @tbid nvarchar(50), @ErrorCode nvarchar(50),
-    //     @retmsg nvarchar(4000)
-    //     Select @tbid='', @ErrorCode='',@retmsg=''
-    //     Select @tbid=${primaryKey} from ${btn.sql} where ${primaryKey} ='${primaryId}'
-    //     If @tbid=''
-    //     Begin
-    //       Setect @ErrorCode='E',@retmsg='鏁版嵁宸插け鏁�'
-    //       goto aaa
-    //     end
-    //     `
-    // }
+    if (formdata) { // 鑾峰彇瀛楁閿�煎
+      formdata.forEach(form => {
+        _formFieldValue[form.key] = form.value
+      })
+    }
 
-    console.log(btn)
-    console.log(formdata)
-    console.log(primaryId)
+    let primaryKey = setting.primaryKey || 'id' // 涓婚敭瀛楁
+    // 绯荤粺鍙橀噺澹版槑涓庤缃垵濮嬪��
+    let _sql = `Declare @tbid nvarchar(50), @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@BillCode nvarchar(50),@BVoucher nvarchar(50),@FIBVoucherDate nvarchar(50), @FiYear nvarchar(50)
+      Select @tbid='', @ErrorCode='',@retmsg='',@BVoucher='',@FIBVoucherDate='',@FiYear=''
+      `
+
+    if (verify && verify.accountdate === 'true') { // 鍚敤璐︽湡楠岃瘉
+      _sql += `exec s_FIBVoucherDateCheck @ErrorCode=@ErrorCode OUTPUT,@retmsg=@retmsg OUTPUT
+        if @ErrorCode!=''
+          GOTO aaa
+        `
+    }
+    if (btn.sqlType !== 'insert' && verify && verify.invalid === 'true') { // 澶辨晥楠岃瘉锛屾坊鍔犳暟鎹椂涓嶇敤
+      _sql += `Select @tbid=${primaryKey} from ${btn.sql} where ${primaryKey} ='${primaryId}'
+        If @tbid=''
+        Begin
+          Setect @ErrorCode='E',@retmsg='鏁版嵁宸插け鏁�'
+          goto aaa
+        end
+        `
+    }
+    if (formdata && verify && verify.uniques.length > 0) { // 鍞竴鎬ч獙璇侊紝蹇呴』瀛樺湪琛ㄥ崟锛堣〃鍗曞瓨鍦ㄦ椂锛屼富閿潎涓哄崟鍊硷級
+      let _primaryId = primaryId
+      if (btn.sqlType === 'insert') {
+        _primaryId = ''
+      }
+      verify.uniques.forEach(item => {
+        let _fieldValue = [] // 琛ㄥ崟閿�煎field=value
+        let _value = []      // 琛ㄥ崟鍊硷紝鐢ㄤ簬閿欒鎻愮ず
+
+        item.field.split(',').forEach(_field => {
+          _fieldValue.push(`${_field}='${_formFieldValue[_field]}'`)
+          _value.push(_formFieldValue[_field])
+        })
+
+        _sql += `Select @tbid='', @ErrorCode='',@retmsg=''
+          Select @tbid='X' from ${btn.sql} where ${_fieldValue.join(' and ')} and ${primaryKey} !='${_primaryId}'
+          If @tbid!=''
+          Begin
+            Setect @ErrorCode='${item.errorCode}',@retmsg='${item.fieldlabel || ''}锛�${_value.join(' ')} 宸插瓨鍦�' 
+            goto aaa
+          end
+          `
+      })
+    }
+    
+    if (verify && verify.customverifys.length > 0) { // 鑷畾涔夐獙璇�
+      verify.customverifys.forEach(item => {
+        let _cuSql = item.sql
+        if (data) {
+          _formFieldValue = {...data, ..._formFieldValue}
+        }
+        let keys = Object.keys(_formFieldValue)
+        keys = keys.sort((a, b) => {
+          return b.length - a.length
+        })
+        keys.forEach(key => {
+          _cuSql.replace('@' + key, _formFieldValue[key])
+        })
+
+        _sql += `Select @tbid='', @ErrorCode='',@retmsg=''
+          Select top 1 @tbid='X' from (${_cuSql}) a
+          If @tbid ${item.result === 'true' ? '=' : '!='}''
+          Begin
+            Setect @ErrorCode='${item.errorCode}',@retmsg='${item.errmsg}'
+            goto aaa
+          end
+          `
+      })
+    }
+
+    if (verify && verify.billcodes.length > 0) {
+      verify.billcodes.forEach(item => {
+        let _ModularDetailCode = ''
+        if (item.TypeCharOne === 'Lp' || item.TypeCharOne === 'BN') {
+          _ModularDetailCode = item.TypeCharOne + item.linkField
+        } else {
+          _ModularDetailCode = item.ModularDetailCode
+        }
+        _sql += `Declare @${item.field} nvarchar(50)
+          select @BillCode='', @${item.field}=''
+          exec s_get_BillCode
+            @ModularDetailCode='${_ModularDetailCode}',
+            @Type=${item.Type},
+            @TypeCharOne='${item.TypeCharOne}',
+            @TypeCharTwo ='${item.TypeCharTwo}',
+            @BillCode =@BillCode output,
+            @ErrorCode =@ErrorCode output, 
+            @retmsg=@retmsg output
+          if @ErrorCode!=''
+            goto aaa
+          set @${item.field}=@BillCode
+          `
+      })
+    }
+
+    if (verify && verify.voucher && verify.voucher.enabled) { // 鍑瘉-鏄剧ず鍒椾腑閫夊彇,蹇呴』閫夎
+      let _voucher = verify.voucher
+
+      _sql += `exec s_BVoucher_Create
+          @Bill ='${data[_voucher.linkField]}',
+          @BVoucherType ='${_voucher.BVoucherType}',
+          @VoucherTypeOne ='${_voucher.VoucherTypeOne}',
+          @VoucherTypeTwo ='${_voucher.VoucherTypeTwo}',
+          @Type =${_voucher.Type},
+          @BVoucher =@BVoucher OUTPUT ,
+          @FIBVoucherDate =@FIBVoucherDate OUTPUT ,
+          @FiYear =@FiYear OUTPUT ,
+          @ErrorCode =@ErrorCode OUTPUT, 
+          @retmsg=@retmsg OUTPUT
+        if @ErrorCode!=''
+          GOTO aaa
+        `
+    }
+
     if (btn.OpenType === 'pop' && btn.sqlType === 'insert') {
       let keys = []
       let values = []
       formdata.forEach(item => {
-        if (!item.readonly && item.type === 'number') {
+        if (item.type === 'number') {
           keys.push(item.key)
           values.push(item.value)
-        } else if (!item.readonly) {
+        } else {
           keys.push(item.key)
           values.push('\'' + item.value + '\'')
         }
@@ -494,19 +592,23 @@
     } else if (btn.OpenType === 'pop' && btn.sqlType === 'update') {
       let _form = []
       formdata.forEach(item => {
-        if (!item.readonly && item.type === 'number') {
+        if (item.type === 'number') {
           _form.push(item.key + '=' + item.value)
-        } else if (!item.readonly) {
+        } else {
           _form.push(item.key + '=\'' + item.value + '\'')
         }
       })
       _form = _form.join(',')
-      _sql += `update ${btn.sql} set ${_form},modifydate=getdate(),modifyuserid=@userid where ${primaryKey}=@${primaryKey}`
+      _sql += `update ${btn.sql} set ${_form},modifydate=getdate(),modifyuserid=@userid,BVoucher=@BVoucher,FIBVoucherDate=@FIBVoucherDate,FiYear=@FiYear where ${primaryKey}=@${primaryKey}`
     } else if ((btn.OpenType === 'prompt' || btn.OpenType === 'exec') && btn.sqlType === 'LogicDelete') { // 閫昏緫鍒犻櫎
       _sql += `update ${btn.sql} set deleted=1,modifydate=getdate(),modifyuserid=@userid where ${primaryKey}=@${primaryKey}`
     } else if ((btn.OpenType === 'prompt' || btn.OpenType === 'exec') && btn.sqlType === 'delete') {
       _sql += `insert into snote (remark,createuserid) select '鍒犻櫎琛�:${btn.sql} 鏁版嵁: ${primaryKey}='+@${primaryKey},@userid delete ${btn.sql} where ${primaryKey}=@${primaryKey}`
     }
+    _sql += `
+      aaa:
+      select @ErrorCode= as ErrorCode,@retmsg as ErrorCode
+      `
     console.log(_sql)
     return _sql
   }
@@ -652,7 +754,6 @@
    * @return {String}
    */
   static getfunc (param, btn, menu, config) {
-    console.log(menu)
     let form = ''
     let formParam = ''
     let columns = config.columns

--
Gitblit v1.8.0