From d891a5169bef4e64ca8acd354bfe5eab75dbbb4d Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 18 十月 2023 17:33:14 +0800
Subject: [PATCH] Merge branch 'develop'

---
 src/tabviews/zshare/actionList/index.scss                                |    8 
 src/views/systemproc/proc/index.jsx                                      |    2 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx |   12 
 src/templates/zshare/modalform/index.jsx                                 |  245 ++++
 src/templates/zshare/editTable/index.jsx                                 |   75 +
 src/templates/modalconfig/settingform/index.scss                         |    4 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx   |   12 
 src/menu/components/form/simple-form/index.jsx                           |   66 -
 src/views/tabledesign/source.jsx                                         |   24 
 src/menu/components/table/base-table/index.scss                          |    3 
 src/menu/components/table/normal-table/index.scss                        |    3 
 src/templates/modalconfig/index.jsx                                      |   67 -
 src/tabviews/zshare/topSearch/index.scss                                 |    2 
 src/mob/modalconfig/index.jsx                                            |   67 -
 src/tabviews/zshare/actionList/normalbutton/index.jsx                    |    7 
 src/tabviews/zshare/mutilform/mkPopSelect/index.scss                     |   64 +
 src/menu/components/table/edit-table/columns/editColumn/index.jsx        |   62 +
 src/templates/modalconfig/dragelement/card.jsx                           |    4 
 src/templates/zshare/editTable/index.scss                                |   13 
 src/menu/sysinterface/index.jsx                                          |    6 
 src/views/systemproc/transfer/index.jsx                                  |  289 +++++
 src/menu/datasource/verifycard/index.jsx                                 |   53 +
 src/assets/css/main.scss                                                 |   19 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx   |   12 
 src/menu/components/table/edit-table/index.scss                          |    5 
 src/menu/components/share/pastecomponent/index.jsx                       |   16 
 src/menu/components/form/step-form/index.jsx                             |   64 -
 src/templates/modalconfig/settingform/index.jsx                          |   33 
 src/templates/zshare/formconfig.jsx                                      |  324 ++++++
 src/menu/components/form/tab-form/index.jsx                              |   64 -
 src/menu/components/share/actioncomponent/index.jsx                      |   10 
 src/menu/modulecell/index.jsx                                            |    4 
 src/tabviews/zshare/actionList/printbutton/index.jsx                     |    7 
 src/tabviews/zshare/mutilform/mkPopSelect/index.jsx                      |  372 +++++++
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss       |    7 
 src/tabviews/zshare/mutilform/index.jsx                                  |  187 ++-
 /dev/null                                                                |   14 
 src/menu/modalconfig/index.scss                                          |   15 
 src/menu/modalconfig/index.jsx                                           |   71 -
 src/menu/components/table/normal-table/index.jsx                         |   16 
 src/menu/components/table/normal-table/columns/index.jsx                 |   34 
 src/templates/zshare/modalform/modaleditable/index.jsx                   |  519 +++++----
 src/views/systemproc/transfer/index.scss                                 |   18 
 src/templates/zshare/modalform/modaleditable/index.scss                  |   12 
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx        |   66 +
 45 files changed, 2,211 insertions(+), 766 deletions(-)

diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 25d2b93..9200e4f 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -321,6 +321,25 @@
   .ant-modal {
     max-width: 95vw;
     top: 70px;
+
+    .ant-modal-title {
+      height: 22px;
+      .mk-modal-icon-def {
+        margin-right: 10px;
+        background: transparent!important;
+      }
+      .mk-modal-icon-circle {
+        display: inline-block;
+        border-radius: 30px;
+        margin-right: 10px;
+        margin-top: -5px;
+        color: #ffffff!important;
+        width: 30px;
+        height: 30px;
+        text-align: center;
+        line-height: 30px;
+      }
+    }
   }
   .ant-modal-body {
     max-height: calc(100vh - 205px);
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index ba3c39c..f267c58 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -1,10 +1,9 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Popover, Modal, Button, Switch, notification, message } from 'antd'
+import { Popover, Modal, Button, Switch, message } from 'antd'
 import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
 
-import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
@@ -399,68 +398,33 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.card).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.card).toJS()
 
+    this.formRef.handleConfirm(_config.subcards[0].fields).then(res => {
       _config.subcards[0].fields = _config.subcards[0].fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
         delete item.focus
 
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
-      window.GLOB.formId = res.uuid
-      
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
 
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
-
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              editform: null,
-              visible: false
-            })
-            this.updateComponent(_config)
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            editform: null,
+            visible: false
+          })
+          this.updateComponent(_config)
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index bfa2708..f4f7947 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -4,7 +4,6 @@
 import { Popover, Modal, Button, Switch, notification, message } from 'antd'
 import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
 
-import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
@@ -501,68 +500,33 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.group).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.group).toJS()
 
+    this.formRef.handleConfirm(_config.fields).then(res => {
       _config.fields = _config.fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
         delete item.focus
 
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
-      window.GLOB.formId = res.uuid
-      
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
 
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
-
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-        
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              editform: null,
-              visible: false
-            })
-            this.updateGroup(_config)
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            editform: null,
+            visible: false
+          })
+          this.updateGroup(_config)
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index 0d6e367..847f7af 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -4,7 +4,6 @@
 import { Popover, Modal, Button, Switch, notification, message } from 'antd'
 import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
 
-import Api from '@/api'
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 import { getModalForm } from '@/templates/zshare/formconfig'
@@ -506,68 +505,33 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.group).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.group).toJS()
 
+    this.formRef.handleConfirm(_config.fields).then(res => {
       _config.fields = _config.fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
         delete item.focus
 
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
-      window.GLOB.formId = res.uuid
-
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
-        
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
 
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-        
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              editform: null,
-              visible: false
-            })
-            this.updateGroup(_config)
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            editform: null,
+            visible: false
+          })
+          this.updateGroup(_config)
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
diff --git a/src/menu/components/share/actioncomponent/index.jsx b/src/menu/components/share/actioncomponent/index.jsx
index 3599e68..a66f2fa 100644
--- a/src/menu/components/share/actioncomponent/index.jsx
+++ b/src/menu/components/share/actioncomponent/index.jsx
@@ -407,10 +407,11 @@
             btn.style = item.style || {}
             if (btn.class) {
               if (btn.class !== item.class || btn.show !== item.show || !btn.style.color || (item.focus && !btn.style.color)) {
-                if (btn.show === 'icon') {
-                  btn.style.color = color[btn.class]
-                  btn.style.backgroundColor = 'transparent'
-                } else if (btn.class === 'default') {
+                // if (btn.show === 'icon') {
+                //   btn.style.color = color[btn.class]
+                //   btn.style.backgroundColor = 'transparent'
+                // } 
+                if (btn.class === 'default') {
                   btn.style.color = 'rgba(0, 0, 0, 0.65)'
                   btn.style.backgroundColor = '#fff'
                   btn.style.borderColor = '#d9d9d9'
@@ -419,6 +420,7 @@
                   btn.style.color = color[_c]
                   btn.style.backgroundColor = '#fff'
                   btn.style.borderColor = color[_c]
+                  btn.style.borderWidth = '1px'
                 } else if (btn.class === 'gray') {
                   btn.style.color = 'rgba(0, 0, 0, 0.65)'
                   btn.style.backgroundColor = color[btn.class]
diff --git a/src/menu/components/share/pastecomponent/index.jsx b/src/menu/components/share/pastecomponent/index.jsx
index 5c2b417..d809808 100644
--- a/src/menu/components/share/pastecomponent/index.jsx
+++ b/src/menu/components/share/pastecomponent/index.jsx
@@ -170,11 +170,23 @@
 
         let keys = config.cols.map(col => (col.field || '$empty'))
 
+        let cols = []
         res.cols.forEach(col => {
-          if (!keys.includes(col.field)) {
-            config.cols.push(col)
+          if (!col.field || !keys.includes(col.field)) {
+            cols.push(col)
           }
         })
+
+        if (cols.length === 0) {
+          notification.warning({
+            top: 92,
+            message: '鏄剧ず鍒楀凡瀛樺湪锛�',
+            duration: 5
+          })
+          return
+        } else {
+          config.cols.push(...cols)
+        }
       }
 
       this.props.updateConfig(config, type)
diff --git a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
index 0ebdd54..aed7101 100644
--- a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -33,6 +33,12 @@
     value: 'number',
     text: '鏁板瓧'
   }, {
+    value: 'custom',
+    text: '鑷畾涔夊垪'
+  }, {
+    value: 'formula',
+    text: '鍏紡'
+  }, {
     value: 'picture',
     text: '鍥剧墖'
   }, {
@@ -45,14 +51,8 @@
     value: 'textarea',
     text: '澶氳鏂囨湰'
   }, {
-    value: 'custom',
-    text: '鑷畾涔夊垪'
-  }, {
     value: 'colspan',
     text: '鍚堝苟鍒�'
-  }, {
-    value: 'formula',
-    text: '鍏紡'
   }, {
     value: 'index',
     text: '搴忓彿'
diff --git a/src/menu/components/table/base-table/index.scss b/src/menu/components/table/base-table/index.scss
index 408f2e5..80333d5 100644
--- a/src/menu/components/table/base-table/index.scss
+++ b/src/menu/components/table/base-table/index.scss
@@ -47,6 +47,9 @@
       padding-top: 10px;
       min-height: 55px;
     }
+    button {
+      min-width: 60px;
+    }
   }
   .model-menu-action-list:not(.length0):not(.length1):not(.length2):not(.length3):not(.length4):not(.length5):not(.length6):not(.length7):not(.length8):not(.length9) {
     margin-bottom: 20px;
diff --git a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
index 9b72d05..8d56325 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx
@@ -25,18 +25,18 @@
     value: 'number',
     text: '鏁板瓧'
   }, {
-    value: 'textarea',
-    text: '澶氳鏂囨湰'
-  }, {
     value: 'custom',
     text: '鑷畾涔夊垪'
   }, {
-    value: 'colspan',
-    text: '鍚堝苟鍒�'
-  }, {
     value: 'formula',
     text: '鍏紡'
   }, {
+    value: 'textarea',
+    text: '澶氳鏂囨湰'
+  }, {
+    value: 'colspan',
+    text: '鍚堝苟鍒�'
+  }, {
     value: 'index',
     text: '搴忓彿'
   }]
diff --git a/src/menu/components/table/edit-table/columns/editColumn/index.jsx b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
index bfc6cad..595109f 100644
--- a/src/menu/components/table/edit-table/columns/editColumn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/editColumn/index.jsx
@@ -382,8 +382,19 @@
         className = 'text-area'
 
         let linkSubFields = this.record.linkSubField || []
+
+        let columns = []
+
+        columns.push({ title: 'Value', key: 'Value', strict: true })
+        columns.push({ title: 'Text', key: 'Text' })
+
+        linkSubFields.forEach(field => {
+          if (field === 'Value' || field === 'Text') return
+
+          columns.push({ title: transfield[field] || field, key: field })
+        })
       
-        content = <EditTable type={'select'} module="form" transfield={transfield} linkSubFields={linkSubFields} onChange={this.changeOptions}/>
+        content = <EditTable columns={columns} module="form" onChange={this.changeOptions}/>
       }
 
       fields.push(
@@ -403,6 +414,29 @@
       )
     })
     return fields
+  }
+
+  transfer = (options) => {
+    if (options.length === 0) return options
+
+    let isNumber = true
+    options.forEach(item => {
+      if (!item.Value || isNaN(item.Value)) {
+        isNumber = false
+      }
+    })
+
+    if (isNumber) {
+      return options.map(item => {
+        item.Value = +item.Value
+        return item
+      })
+    } else {
+      return options.map(item => {
+        item.Value = item.Value + ''
+        return item
+      })
+    }
   }
 
   handleSubmit = () => {
@@ -431,6 +465,32 @@
           cols.forEach(col => {
             values.formula = values.formula.replace(col.reg, col.value)
           })
+        } else if (values.type === 'text' && values.editable === 'true' && values.editType === 'select') {
+          if (values.resourceType === '0') {
+            values.options = values.options || []
+            
+            values.options = this.transfer(values.options)
+
+            if (values.options.filter(op => op.Text === '').length > 0) {
+              notification.warning({
+                top: 92,
+                message: '鎻愮ず鏂囨湰锛圱ext锛変笉鍙负绌猴紒',
+                duration: 5
+              })
+              return
+            } else {
+              let arr = values.options.map(m => m.Value)
+              let _arr = Array.from(new Set(arr))
+              if (arr.length > _arr.length) {
+                notification.warning({
+                  top: 92,
+                  message: 'Value鍊间笉鍙噸澶嶏紒',
+                  duration: 5
+                })
+                return
+              }
+            }
+          }
         }
 
         if (values.dataSource && /\s/.test(values.dataSource)) {
diff --git a/src/menu/components/table/edit-table/index.scss b/src/menu/components/table/edit-table/index.scss
index 60bc249..cfe7fcc 100644
--- a/src/menu/components/table/edit-table/index.scss
+++ b/src/menu/components/table/edit-table/index.scss
@@ -6,7 +6,7 @@
   background-repeat: no-repeat;
   background-size: cover;
   min-height: 100px;
-  
+
   .model-table-search-list {
     padding: 10px 0px 15px;
     min-height: 65px;
@@ -73,6 +73,9 @@
       padding-top: 10px;
       min-height: 55px;
     }
+    button {
+      min-width: 60px;
+    }
   }
 
   .ant-btn.mk-link {
diff --git a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
index f915309..8dd1c49 100644
--- a/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
+++ b/src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx
@@ -40,6 +40,12 @@
     value: 'number',
     text: '鏁板瓧'
   }, {
+    value: 'custom',
+    text: '鑷畾涔夊垪'
+  }, {
+    value: 'formula',
+    text: '鍏紡'
+  }, {
     value: 'picture',
     text: '鍥剧墖'
   }, {
@@ -52,14 +58,8 @@
     value: 'textarea',
     text: '澶氳鏂囨湰'
   }, {
-    value: 'custom',
-    text: '鑷畾涔夊垪'
-  }, {
     value: 'colspan',
     text: '鍚堝苟鍒�'
-  }, {
-    value: 'formula',
-    text: '鍏紡'
   }, {
     value: 'index',
     text: '搴忓彿'
diff --git a/src/menu/components/table/normal-table/columns/index.jsx b/src/menu/components/table/normal-table/columns/index.jsx
index 02653b8..cae43f6 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -37,6 +37,32 @@
     this.props.updateCol({...column, marks: vals})
   }
 
+  copycolumn = () => {
+    const { column } = this.props
+
+    let oInput = document.createElement('input')
+    let val = {
+      copyType: 'cols',
+      cols: [column]
+    }
+
+    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    if (srcid) {
+      val.$srcId = srcid
+    }
+
+    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
+    document.body.appendChild(oInput)
+    oInput.select()
+    document.execCommand('Copy')
+    oInput.className = 'oInput'
+    oInput.style.display = 'none'
+
+    message.success('澶嶅埗鎴愬姛銆�')
+
+    document.body.removeChild(oInput)
+  }
+
   shouldComponentUpdate (nextProps, nextState) {
 
     if (this.props.rowSpan !== nextProps.rowSpan || this.props.colSpan !== nextProps.colSpan) {
@@ -76,6 +102,7 @@
             {column.type === 'custom' ? <PlusOutlined className="plus" title="娣诲姞鍏冪礌" onClick={() => this.props.addElement(column)} /> : null}
             {column.type === 'custom' ? <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={() => this.props.addElement(column, 'button')} /> : null}
             <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+            <CopyOutlined title="澶嶅埗鏄剧ず鍒�" style={{color: '#26C281'}} onClick={this.copycolumn} />
             {column.type === 'custom' ? <PasteComponent options={['customCardElement', 'action']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
             {column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
             <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
@@ -597,6 +624,12 @@
     })
   }
 
+  addColumns = () => {
+    const { config } = this.props
+
+    MKEmitter.emit('addColumns', config.uuid)
+  }
+
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
    */
@@ -623,6 +656,7 @@
     return (
       <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''} table-vertical-${config.wrap.vertical || ''} table-col-${columns.length}`} id={tableId}>
         <div className="col-control">
+          <PlusOutlined style={{color: '#26C281'}} title="娣诲姞鍒�" onClick={this.addColumns}/>
           <CopyOutlined title="澶嶅埗鏄剧ず鍒�" onClick={this.copycolumn} />
           <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
           <FileSyncOutlined title="鍚屾瀛楁闆�" onClick={this.syncfield} />
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index 4b011c7..5a6fd01 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -92,6 +92,7 @@
 
   componentDidMount () {
     MKEmitter.addListener('completeSave', this.completeSave)
+    MKEmitter.addListener('addColumns', this.addColumns)
   }
 
   shouldComponentUpdate (nextProps, nextState) {
@@ -106,6 +107,7 @@
       return
     }
     MKEmitter.removeListener('completeSave', this.completeSave)
+    MKEmitter.removeListener('addColumns', this.addColumns)
   }
 
   completeSave = () => {
@@ -210,12 +212,16 @@
     this.updateComponent(_card)
   }
 
-  addColumns = () => {
-    let card = fromJS(this.state.card).toJS()
+  addColumns = (id) => {
+    const { card } = this.state
 
-    card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
+    if (id && id !== card.uuid) return
 
-    this.setState({card})
+    let _card = fromJS(card).toJS()
+
+    _card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
+
+    this.setState({card: _card})
   }
 
   addSearch = () => {
@@ -365,7 +371,7 @@
         <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
-            <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={this.addColumns}/>
+            <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={() => this.addColumns()}/>
             {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch}/> : null}
             <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton}/>
             <NormalForm title="琛ㄦ牸璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
diff --git a/src/menu/components/table/normal-table/index.scss b/src/menu/components/table/normal-table/index.scss
index c5c5f42..d14a40e 100644
--- a/src/menu/components/table/normal-table/index.scss
+++ b/src/menu/components/table/normal-table/index.scss
@@ -73,6 +73,9 @@
       padding-top: 10px;
       min-height: 55px;
     }
+    button {
+      min-width: 60px;
+    }
   }
 
   .ant-btn.mk-link {
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 8da4cb7..1ef5833 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -678,6 +678,55 @@
             resolve()
           })
         } else {
+          if (/鍒楀悕\s*'[a-zA-Z0-9_-]+'\s*鏃犳晥/.test(result.message)) {
+            let tail = ''
+            let type = ''
+            searches.forEach(item => {
+              if (item.forbid) return
+              item.key.split(',').forEach(field => {
+                if (new RegExp(`'${field}'`).test(result.message)) {
+                  tail = field
+                  type = '鎼滅储鏉′欢'
+                }
+              })
+            })
+
+            if (!tail) {
+              let keys = setting.order.replace(/\s+(asc|desc)/ig, '').replace(/\s+/g, '')
+              keys.split(',').forEach(field => {
+                if (new RegExp(`'${field}'`).test(result.message)) {
+                  tail = field
+                  type = '鎺掑簭'
+                }
+              })
+            }
+
+            if (!tail) {
+              columns.forEach(item => {
+                if (new RegExp(`'${item.field}'`).test(result.message)) {
+                  tail = item.field
+                  if (config.subtype === 'basetable') {
+                    type = '鏄剧ず鍒�'
+                  } else {
+                    type = '瀛楁闆�'
+                  }
+                }
+              })
+              if (!tail && config.subtype === 'dualdatacard') {
+                subColumns.forEach(item => {
+                  if (new RegExp(`'${item.field}'`).test(result.message)) {
+                    tail = item.field
+                    type = '瀛愯〃瀛楁闆�'
+                  }
+                })
+              }
+            }
+
+            if (tail) {
+              result.message = result.message.replace(/ROLLBACK TRANSACTION 璇锋眰娌℃湁瀵瑰簲鐨� BEGIN TRANSACTION銆�/, '')
+              result.message = <>{result.message}<span style={{color: 'red'}}>娉細{type}涓瓨鍦ㄥ瓧娈祘tail}</span></>
+            }
+          }
           if (type === 'submit') {
             Modal.confirm({
               title: result.message,
@@ -1078,8 +1127,8 @@
             <span>
               鑷畾涔夎剼鏈�
               {scripts.length ? <span className="count-tip">{scripts.length}</span> : null}
-              {config.type !== 'interface' && activeKey === 'setting' ? <CopyOutlined title="澶嶅埗鏁版嵁婧�" className="mk-copy-datasource" onClick={(e) => {e.stopPropagation();this.copyDatasource()}}/> : null}
-              {config.type !== 'interface' && activeKey === 'setting' ? <SnippetsOutlined title="瀵煎叆鏁版嵁婧�" className="mk-paste-datasource" onClick={(e) => {e.stopPropagation();this.setState({pvisible: true})}}/> : null}
+              {activeKey === 'setting' ? <CopyOutlined title="澶嶅埗鏁版嵁婧�" className="mk-copy-datasource" onClick={(e) => {e.stopPropagation();this.copyDatasource()}}/> : null}
+              {activeKey === 'setting' ? <SnippetsOutlined title="瀵煎叆鏁版嵁婧�" className="mk-paste-datasource" onClick={(e) => {e.stopPropagation();this.setState({pvisible: true})}}/> : null}
               {activeKey === 'columns' ? <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copyColumns()}}/> : null}
               {activeKey === 'subcolumns' ? <CopyOutlined title="浠ラ�楀彿鎷兼帴褰㈠紡澶嶅埗瀛楁" className="mk-copy-fields" onClick={(e) => {e.stopPropagation();this.copySubColumns()}}/> : null}
               {activeKey === 'subcolumns' || activeKey === 'columns' ? <span onClick={(e) => {e.stopPropagation()}}><Search className="mk-search-fields" defaultValue={searchKey} allowClear onSearch={(val, e) => {e.stopPropagation();this.setState({searchKey: val})}} /></span> : null}
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index ced3019..8bb149f 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -3,12 +3,10 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { Button, Card, Modal, Collapse, notification, Switch, message } from 'antd'
+import { Button, Card, Modal, Collapse, Switch, message } from 'antd'
 import { SettingOutlined, CopyOutlined } from '@ant-design/icons'
 
-import Api from '@/api'
 import { getModalForm } from '@/templates/zshare/formconfig'
-
 import SourceElement from '@/templates/modalconfig/dragelement/source'
 import SettingForm from '@/templates/modalconfig/settingform'
 import asyncComponent from '@/utils/asyncComponent'
@@ -18,6 +16,8 @@
 
 const { Panel } = Collapse
 const { confirm } = Modal
+
+const MkIcon = asyncComponent(() => import('@/components/mk-icon'))
 const TableComponent = asyncComponent(() => import('./tablecomponent'))
 const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
 const PasteForms = asyncComponent(() => import('@/menu/components/share/pasteforms'))
@@ -225,68 +225,33 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.config).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.config).toJS()
 
+    this.formRef.handleConfirm(_config.fields).then(res => {
       _config.fields = _config.fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
         delete item.focus
 
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
-      window.GLOB.formId = res.uuid
-
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
 
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
-
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-        
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              config: _config,
-              card: null,
-              visible: false
-            })
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            config: _config,
+            card: null,
+            visible: false
+          })
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
@@ -538,7 +503,7 @@
               <SettingOutlined onClick={this.changeSetting} />
               <div className="ant-modal-content" style={{width: config.setting.width > 100 ? config.setting.width : config.setting.width + '%'}}>
                 <div className="ant-modal-header">
-                  <div className="ant-modal-title">{btn.label}</div>
+                  <div className="ant-modal-title">{config.setting.icon ? <span className={'mk-modal-icon-' + config.setting.iconType} style={{background: config.setting.iconColor || 'unset', color: config.setting.iconColor || 'inherit'}}><MkIcon type={config.setting.icon}/></span> : null}{btn.label}</div>
                   <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button>
                   <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button>
                   <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button>
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index 723def0..d73bd57 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -120,6 +120,21 @@
           padding-right: 80px;
           .ant-modal-title {
             display: inline-block;
+            height: 22px;
+            .mk-modal-icon-def {
+              margin-right: 10px;
+              background: transparent!important;
+            }
+            .mk-modal-icon-circle {
+              display: inline-block;
+              border-radius: 30px;
+              margin-right: 10px;
+              color: #ffffff!important;
+              width: 30px;
+              height: 30px;
+              text-align: center;
+              line-height: 30px;
+            }
           }
           .anticon-copy {
             position: absolute;
diff --git a/src/menu/modulecell/index.jsx b/src/menu/modulecell/index.jsx
index e88c740..e3825af 100644
--- a/src/menu/modulecell/index.jsx
+++ b/src/menu/modulecell/index.jsx
@@ -93,13 +93,13 @@
         children: [
           { subType: 'text', text: '鏂囨湰', type: 'col', $init: true },
           { subType: 'number', text: '鏁板瓧', type: 'col', $init: true },
+          { subType: 'custom', text: '鑷畾涔夊垪', type: 'col', $init: true },
+          { subType: 'formula', text: '鍏紡', type: 'col', $init: true },
           { subType: 'picture', text: '鍥剧墖', type: 'col', $init: true },
           { subType: 'video', text: '瑙嗛', type: 'col', $init: true },
           { subType: 'link', text: '閾炬帴', type: 'col', $init: true },
           { subType: 'textarea', text: '澶氳鏂囨湰', type: 'col', $init: true },
-          { subType: 'custom', text: '鑷畾涔夊垪', type: 'col', $init: true },
           { subType: 'colspan', text: '鍚堝苟鍒�', type: 'col', $init: true },
-          { subType: 'formula', text: '鍏紡', type: 'col', $init: true },
           { subType: 'index', text: '搴忓彿', type: 'col', $init: true }
         ]
       }
diff --git a/src/menu/sysinterface/index.jsx b/src/menu/sysinterface/index.jsx
index 6c88dcc..1504093 100644
--- a/src/menu/sysinterface/index.jsx
+++ b/src/menu/sysinterface/index.jsx
@@ -176,7 +176,7 @@
     let trimreg = /(from|update|insert\s+into)\s+(@db@)?/ig
 
     if (record.setting.interType === 'system') {
-      if (record.setting.execute !== 'false') {
+      if (record.setting.execute !== 'false' && record.setting.dataresource) {
         let tbs = record.setting.dataresource.match(cutreg)
         tbs && cuts.push(...tbs)
       }
@@ -185,7 +185,7 @@
         let tbs = script.sql.match(cutreg)
         tbs && cuts.push(...tbs)
       })
-    } else {
+    } else if (record.setting.tableName) {
       let tb = record.setting.tableName.replace(/@db@|\s+/ig, '')
       if (/[a-z_]+/ig.test(tb)) {
         tables.push(tb)
@@ -211,6 +211,8 @@
     record.name = record.setting.name
     record.$tables = this.getTables(record)
 
+    delete record.subColumns
+
     let interfaces = this.state.interfaces.map(item => {
       if (item.uuid !== record.uuid) {
         return item
diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx
index a408c9a..803af96 100644
--- a/src/mob/modalconfig/index.jsx
+++ b/src/mob/modalconfig/index.jsx
@@ -3,12 +3,10 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { Button, Modal, Collapse, notification, Switch, message } from 'antd'
+import { Button, Modal, Collapse, Switch, message } from 'antd'
 import { LeftOutlined } from '@ant-design/icons'
 
-import Api from '@/api'
 import { getModalForm } from '@/templates/zshare/formconfig'
-
 import SourceElement from '@/templates/modalconfig/dragelement/source'
 import SettingForm from '@/templates/modalconfig/settingform'
 import asyncComponent from '@/utils/asyncComponent'
@@ -222,68 +220,33 @@
    * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.config).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.config).toJS()
 
+    this.formRef.handleConfirm(_config.fields).then(res => {
       _config.fields = _config.fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
         delete item.focus
 
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
-      window.GLOB.formId = res.uuid
-
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
 
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
-
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-        
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              config: _config,
-              card: null,
-              visible: false
-            })
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            config: _config,
+            card: null,
+            visible: false
+          })
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
index aa7ebb2..a161a64 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -171,6 +171,13 @@
       }
     }
   }
+  .ant-transfer-operation {
+    margin: 0 15px;
+
+    .ant-btn:first-child {
+      margin-bottom: 10px;
+    }
+  }
 }
 
 .member-modal {
diff --git a/src/tabviews/zshare/actionList/index.scss b/src/tabviews/zshare/actionList/index.scss
index 42c8bcc..1d31f09 100644
--- a/src/tabviews/zshare/actionList/index.scss
+++ b/src/tabviews/zshare/actionList/index.scss
@@ -1,17 +1,21 @@
 .button-list.toolbar-button {
   position: relative;
   padding: 15px 0px 0px;
-  background: #ffffff;
   min-height: 55px;
+  background: transparent;
 
   button {
-    min-width: 65px;
+    min-width: 60px;
     margin-right: 15px;
     margin-bottom: 10px!important;
     overflow: hidden;
     min-height: 28px;
     height: auto;
   }
+  .ant-btn-icon-only {
+    width: auto;
+    padding: 0 15px;
+  }
 
   .loading-skeleton {
     background: -webkit-gradient(linear,left top,right top,color-stop(25%,#f5f5f5),color-stop(37%,#ffffff),color-stop(63%,#f5f5f5));
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index 816e450..4da4369 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -3008,6 +3008,13 @@
         container = () => document.getElementById(btn.ContainerId)
       }
 
+      if (btnconfig.setting.icon) {
+        title = <>
+          <span className={'mk-modal-icon-' + btnconfig.setting.iconType} style={{background: btnconfig.setting.iconColor || 'unset', color: btnconfig.setting.iconColor || 'inherit'}}><MkIcon type={btnconfig.setting.icon}/></span>
+          {title}
+        </>
+      }
+
       return (
         <Modal
           title={title}
diff --git a/src/tabviews/zshare/actionList/printbutton/index.jsx b/src/tabviews/zshare/actionList/printbutton/index.jsx
index 4bd500f..b55792d 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -2238,6 +2238,13 @@
       clickouter = true
     }
 
+    if (btnconfig.setting.icon) {
+      title = <>
+        <span className={'mk-modal-icon-' + btnconfig.setting.iconType} style={{background: btnconfig.setting.iconColor || 'unset', color: btnconfig.setting.iconColor || 'inherit'}}><MkIcon type={btnconfig.setting.icon}/></span>
+        {title}
+      </>
+    }
+
     return (
       <Modal
         title={title}
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index b1f23a7..d4b95fd 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -28,6 +28,7 @@
 const MkFormula = asyncComponent(() => import('./mkFormula'))
 const MkCascader = asyncComponent(() => import('./mkCascader'))
 const MkVercode = asyncComponent(() => import('./mkVercode'))
+const MKPopSelect = asyncComponent(() => import('./mkPopSelect'))
 const MKEditor = asyncComponent(() => import('@/components/editor'))
 
 class MutilFormComponent extends Component {
@@ -125,7 +126,7 @@
         item.precision = 'second'
       }
 
-      if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
+      if (!item.field || !['text', 'number', 'switch', 'check', 'rate', 'select', 'popSelect', 'link', 'cascader', 'linkMain', 'funcvar', 'date', 'datemonth', 'radio', 'checkbox', 'checkcard', 'fileupload', 'textarea', 'multiselect', 'brafteditor', 'color', 'vercode'].includes(item.type)) return false
 
       if (/^\s+$/.test(item.label)) {
         item.style = item.style || {}
@@ -292,26 +293,31 @@
         }
       }
 
+      item.rules = []
       if (item.type === 'text') {
         item.initval = item.initval + ''
-        let _rules = [{
-          pattern: /^[^']*$/ig,
-          message: '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒'
-        }, {
+
+        if (item.required === 'true') {
+          item.rules.push({
+            required: true,
+            message: item.label + '涓嶅彲涓虹┖!'
+          })
+        }
+
+        item.rules.push({
           validator: (rule, value, callback) => {
-            if (/--/ig.test(value)) {
+            if (/'/.test(value)) {
+              callback('涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
+            } else if (/--/.test(value)) {
               callback('涓嶅彲浣跨敤 -- 锛�')
             } else {
               callback()
             }
           }
-        }, {
-          required: item.required === 'true',
-          message: item.label + '涓嶅彲涓虹┖!'
-        }]
-
+        })
+        
         if (!item.lenControl || item.lenControl === 'limit') {
-          _rules.push({
+          item.rules.push({
             max: item.fieldlength,
             message: formRule.input.formMessage.replace('@max', item.fieldlength)
           })
@@ -323,7 +329,7 @@
             if (item.regularExtra) {
               reg = new RegExp('^[0-9.-' + item.regularExtra.replace(/\.|-/g, '') + ']*$')
             }
-            _rules.push({
+            item.rules.push({
               pattern: reg,
               message: item.regularText || formRule.input.numbermsg
             })
@@ -332,7 +338,7 @@
             if (item.regularExtra) {
               reg = new RegExp('^[a-zA-Z' + item.regularExtra + ']*$')
             }
-            _rules.push({
+            item.rules.push({
               pattern: reg,
               message: item.regularText || formRule.input.lettermsg
             })
@@ -341,7 +347,7 @@
             if (item.regularExtra) {
               reg = new RegExp('^[a-zA-Z0-9' + item.regularExtra + ']*$')
             }
-            _rules.push({
+            item.rules.push({
               pattern: reg,
               message: item.regularText || '璇疯緭鍏ユ暟瀛楁垨瀛楁瘝'
             })
@@ -350,80 +356,113 @@
             if (item.regularExtra) {
               reg = new RegExp('^[a-zA-Z0-9@_.' + item.regularExtra.replace(/\.|_|@/g, '') + ']*$')
             }
-            _rules.push({
+            item.rules.push({
               pattern: reg,
               message: item.regularText || '璇疯緭鍏ユ暟瀛椼�佸瓧姣嶄互鍙夽_.'
             })
           } else if (item.regular === 'phone') {
-            _rules.push({
+            item.rules.push({
               pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
               message: item.regularText || '璇锋纭緭鍏ユ墜鏈哄彿'
             })
           } else if (item.regular === 'email') {
-            _rules.push({
+            item.rules.push({
               pattern: /^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/,
               message: item.regularText || '璇锋纭緭鍏ラ偖绠卞湴鍧�'
             })
           }
         }
-        
-        item.rules = _rules
       } else if (item.type === 'number') {
         item.rules = [{
           required: true,
           message: item.label + '涓嶅彲涓虹┖!'
-        }, {
-          validator: (rule, value, callback) => this.handleConfirmPassword(rule, value, callback, item)
         }]
-      } else if (item.type === 'textarea') {
-        let _rules = [
-          {
-            required: item.required === 'true',
-            message: item.label + '涓嶅彲涓虹┖!'
-          },
-          {
-            max: item.fieldlength,
-            message: formRule.input.formMessage.replace('@max', item.fieldlength)
-          },
-          {
-            pattern: /^[^']*$/ig,
-            message: '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒'
-          }, {
+
+        if (typeof(item.min) === 'number' || typeof(item.max) === 'number') {
+          item.rules.push({
             validator: (rule, value, callback) => {
-              if (/--/ig.test(value)) {
-                callback('涓嶅彲浣跨敤 -- 锛�')
+              if (isNaN(value)) {
+                callback()
+              } else if (typeof(item.min) === 'number' && value < item.min) {
+                if (item.min < 1e-6) {
+                  if (item.min === 1e-6) {
+                    callback(item.label + '鏈�灏忓�间负 0.000001')
+                  } else if (item.min === 1e-7) {
+                    callback(item.label + '鏈�灏忓�间负 0.0000001')
+                  } else if (item.min === 1e-8) {
+                    callback(item.label + '鏈�灏忓�间负 0.00000001')
+                  } else if (item.min === 1e-9) {
+                    callback(item.label + '鏈�灏忓�间负 0.000000001')
+                  } else if (item.min === 1e-10) {
+                    callback(item.label + '鏈�灏忓�间负 0.0000000001')
+                  } else if (item.min === 1e-11) {
+                    callback(item.label + '鏈�灏忓�间负 0.00000000001')
+                  } else {
+                    callback(item.label + '鏈�灏忓�间负 ' + item.min)
+                  }
+                } else {
+                  callback(item.label + '鏈�灏忓�间负 ' + item.min)
+                }
+              } else if (typeof(item.max) === 'number' && value > item.max) {
+                callback(item.label + '鏈�澶у�间负 ' + item.max)
               } else {
                 callback()
               }
             }
+          })
+        }
+      } else if (item.type === 'textarea') {
+        if (item.required === 'true') {
+          item.rules.push({
+            required: true,
+            message: item.label + '涓嶅彲涓虹┖!'
+          })
+        }
+
+        item.rules.push({
+          validator: (rule, value, callback) => {
+            if (/'/.test(value)) {
+              callback('涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒')
+            } else if (/--/.test(value)) {
+              callback('涓嶅彲浣跨敤 -- 锛�')
+            } else {
+              callback()
+            }
           }
-        ]
-        item.rules = _rules
+        }, {
+          max: item.fieldlength,
+          message: formRule.input.formMessage.replace('@max', item.fieldlength)
+        })
       } else if (item.type === 'brafteditor') {
-        item.rules = [
-          {
-            required: item.required === 'true',
+        if (item.required === 'true') {
+          item.rules.push({
+            required: true,
             message: item.label + '涓嶅彲涓虹┖!'
-          },
-          {
-            max: item.fieldlength,
-            message: formRule.input.formMessage.replace('@max', item.fieldlength)
-          }
-        ]
+          })
+        }
+
+        item.rules.push({
+          max: item.fieldlength,
+          message: formRule.input.formMessage.replace('@max', item.fieldlength)
+        })
       } else if (item.type === 'linkMain' || item.type === 'vercode') {
-        item.rules = [
-          {
-            required: item.required === 'true',
+        if (item.required === 'true') {
+          item.rules.push({
+            required: true,
             message: item.label + '涓嶅彲涓虹┖!'
-          }
-        ]
+          })
+        }
       } else {
-        item.rules = [
-          {
-            required: item.required === 'true',
+        if (item.required === 'true') {
+          item.rules.push({
+            required: true,
             message: '璇烽�夋嫨' + item.label + '!'
-          }
-        ]
+          })
+        }
+      }
+
+      if (item.rules.length === 0) {
+        item.rules = null
       }
 
       fieldMap.set(item.field, item)
@@ -530,6 +569,18 @@
             reFieldsVal[n.field] = val || ''
           })
         } else if (item.type === 'fileupload') {
+          item.options = []
+          item.subFields = []
+          item.linkSubField.forEach(m => {
+            let n = fieldMap.get(m)
+            if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+              item.subFields.push({
+                uuid: n.uuid,
+                field: m
+              })
+            }
+          })
+        } else if (item.type === 'popSelect') {
           item.options = []
           item.subFields = []
           item.linkSubField.forEach(m => {
@@ -1002,22 +1053,6 @@
     })
   }
 
-  handleConfirmPassword = (rule, value, callback, item) => {
-    let val = parseFloat(value)
-
-    if (!isNaN(val)) {
-      if (typeof(item.min) === 'number' && val < item.min) {
-        callback(item.label + '鏈�灏忓�间负 ' + item.min)
-      } else if (typeof(item.max) === 'number' && val > item.max) {
-        callback(item.label + '鏈�澶у�间负 ' + item.max)
-      } else {
-        callback()
-      }
-    } else {
-      callback()
-    }
-  }
-
   recordChange = (values, item) => {
     this.record = {...this.record, ...values}
 
@@ -1124,6 +1159,8 @@
           content = (<MKNumberInput config={item} onChange={(val, defer) => !defer && this.recordChange({[item.field]: val})} onSubmit={this.props.inputSubmit} />)
         } else if (item.type === 'select' || item.type === 'link' || item.type === 'multiselect') {
           content = (<MKSelect config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />)
+        } else if (item.type === 'popSelect') {
+          content = (<MKPopSelect config={item} BID={this.props.BID} ID={this.state.ID} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)} onSubmit={this.props.inputSubmit} />)
         } else if (item.type === 'cascader') {
           content = (<MkCascader config={item} onChange={(val, other) => this.recordChange({[item.field]: val, ...other}, item)}/>)
         } else if (item.type === 'color') {
diff --git a/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
new file mode 100644
index 0000000..0181c89
--- /dev/null
+++ b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
@@ -0,0 +1,372 @@
+import React, {Component} from 'react'
+import { is, fromJS } from 'immutable'
+import { Select } from 'antd'
+import { notification, Modal, Table, Input } from 'antd'
+import moment from 'moment'
+import { TableOutlined } from '@ant-design/icons'
+
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const { Search } = Input
+
+class MKPopSelect extends Component {
+  constructor(props) {
+    super(props)
+    
+    let config = fromJS(props.config).toJS()
+    let value = config.initval
+
+    let arrfield = config.columns.map(f => f.field)
+  
+    if (config.subFields && config.subFields.length > 0) {
+      config.subFields.forEach(n => {
+        if (!arrfield.includes(n.field)) {
+          arrfield.push(n.field)
+        }
+      })
+    }
+
+    if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+      config.dataSource = config.dataSource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+    } else {
+      config.dataSource = config.dataSource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+    }
+
+    config.dataSource = config.dataSource.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
+    config.dataSource = config.dataSource.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
+    config.dataSource = config.dataSource.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
+    config.dataSource = config.dataSource.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+
+    if (/\s/.test(config.dataSource)) { // 鎷兼帴鍒悕
+      config.dataSource = '(' + config.dataSource + ') tb'
+    }
+
+    let columns = []
+    let labels = {}
+    config.columns.forEach(col => {
+      labels[col.field] = col.label
+
+      if (col.Hide === 'true') return
+
+      columns.push({
+        dataIndex: col.field,
+        title: col.label,
+        sorter: col.IsSort === 'true',
+        width: 120
+      })
+    })
+
+    let placeholder = ''
+    if (!config.searchKey) {
+      config.onload = 'true'
+    } else {
+      placeholder = []
+      config.searchKey.split(',').forEach(key => {
+        if (!labels[key]) {
+          placeholder = ''
+        } else if (placeholder) {
+          placeholder.push(labels[key])
+        }
+      })
+
+      placeholder = placeholder ? placeholder.join('銆�') : ''
+    }
+
+    this.state = {
+      config: config,
+      options: [],
+      columns,
+      value,
+      placeholder,
+      arr_field: arrfield.join(','),
+      searchKey: '',
+      pageIndex: 1,
+      pageSize: 10,
+      orderBy: '',
+      visible: false,
+      loading: false
+    }
+
+    this.timer = null
+  }
+
+  componentDidMount () {
+    const { config } = this.state
+
+    if (config.onload === 'true') {
+      this.loadData()
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  loadData () {
+    const { BID, ID } = this.props
+    const { config, pageIndex, pageSize, arr_field, searchKey, orderBy } = this.state
+
+    this.setState({
+      loading: true
+    })
+
+    let param = {
+      func: 'sPC_Get_TableData',
+      obj_name: 'data',
+      exec_type: 'y',
+      arr_field: arr_field,
+      default_sql: 'true',
+      custom_script: '',
+      menuname: config.label
+    }
+
+    let sql = ''
+    let DateCount = ''
+    let _search = ''
+    let _orderBy = orderBy || config.order || ''
+    let _datasource = config.dataSource
+
+    if (config.searchKey && searchKey) {
+      let fields = config.searchKey.split(',').map(field => field + ` like '%${searchKey}%'`)
+      _search = 'where ' + fields.join(' OR ')
+    }
+
+    _datasource = _datasource.replace(/@BID@/ig, `'${BID || ''}'`)
+    _datasource = _datasource.replace(/@ID@/ig, `'${ID || ''}'`)
+
+    if (config.laypage === 'true') {
+      sql = `/*system_query*/select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
+      DateCount = `/*system_query*/select count(1) as total from ${_datasource} ${_search}`
+    } else if (_orderBy) {
+      sql = `/*system_query*/select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
+    } else {
+      sql = `/*system_query*/select ${arr_field} from ${_datasource} ${_search}  `
+    }
+
+    let departmentcode = sessionStorage.getItem('departmentcode') || ''
+    let organization = sessionStorage.getItem('organization') || ''
+    let mk_user_type = sessionStorage.getItem('mk_user_type') || ''
+    
+    sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+      Select @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}'
+      ${sql}`
+
+    // 娴嬭瘯绯荤粺鎵撳嵃鏌ヨ璇彞
+    if (window.GLOB.debugger === true) {
+      console.info(`/*${config.label} 鏁版嵁婧�*/\n` + sql.replace(/\n\s{6}/ig, '\n'))
+      DateCount && console.info(`/*${config.label} 鎬绘暟鏌ヨ*/\n` + DateCount.replace(/\n\s{6}/ig, '\n'))
+    }
+
+    param.LText = Utils.formatOptions(sql)
+    param.DateCount = Utils.formatOptions(DateCount)
+
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
+    param.secretkey = Utils.encrypt('', param.timestamp)
+
+    param.username = sessionStorage.getItem('User_Name') || ''
+    param.fullname = sessionStorage.getItem('Full_Name') || ''
+
+    Api.genericInterface(param).then(result => {
+      if (result.status) {
+        let options = result.data.map((item, index) => {
+          item.key = index
+          item.$$uuid = item[config.primaryKey] || ''
+          item.$label = item[config.showField]
+
+          if (config.controlField && item[config.controlField] === 'true') {
+            item.$disabled = true
+          }
+
+          return item
+        })
+  
+        this.setState({
+          options: options,
+          total: result.total || 0,
+          loading: false
+        })
+  
+        if (result.message) {
+          if (result.ErrCode === 'Y') {
+            Modal.success({
+              title: result.message
+            })
+          } else if (result.ErrCode === 'S') {
+            notification.success({
+              top: 92,
+              message: result.message,
+              duration: 2
+            })
+          }
+        }
+      } else {
+        this.setState({
+          loading: false
+        })
+  
+        if (!result.message) return
+        if (result.ErrCode === 'N') {
+          Modal.error({
+            title: result.message,
+          })
+        } else if (result.ErrCode !== '-2') {
+          notification.error({
+            top: 92,
+            message: result.message,
+            duration: 10
+          })
+        }
+      }
+    })
+  }
+
+  searchOption = (val) => {
+    this.setState({searchKey: val})
+
+    if (this.timer) {
+      clearTimeout(this.timer)
+    }
+
+    this.timer = setTimeout(() => {
+      this.loadData()
+    }, 500)
+  }
+
+  selectChange = (val, record) => {
+    const { config } = this.state
+    let other = {}
+
+    if (config.subFields) {
+      let option = record || null
+
+      if (!option) {
+        option = this.state.options.filter(m => m.$$uuid === val)[0]
+      }
+
+      option && config.subFields.forEach((n, i) => {
+        other[n.field] = option[n.field]
+        setTimeout(() => {
+          MKEmitter.emit('mkFC', 'input', n.uuid, option[n.field])
+        }, i * 5)
+      })
+    }
+
+    this.props.onChange(val, other)
+    this.setState({value: val}, () => {
+      if (config.enter === 'tab') {
+        MKEmitter.emit('mkFC', 'focus', config.tabUuid)
+      } else if (config.enter === 'sub') {
+        if (config.subFields) {
+          setTimeout(() => {
+            this.props.onSubmit()
+          }, 1000)
+        } else {
+          this.props.onSubmit()
+        }
+      }
+    })
+  }
+
+  trigger = (e) => {
+    e.stopPropagation()
+
+    this.setState({visible: true})
+  }
+
+  changeRow = (record) => {
+
+    if (record.$disabled) return
+
+    this.selectChange(record.$$uuid, record)
+    this.setState({visible: false})
+  }
+
+  changeTable = (pagination, filters, sorter) => {
+    let orderBy = ''
+
+    if (sorter.field && sorter.order) {
+      if (sorter.order === 'ascend') {
+        orderBy = `${sorter.field} asc`
+      } else {
+        orderBy = `${sorter.field} desc`
+      }
+    }
+
+    this.setState({
+      pageIndex: pagination.current,
+      pageSize: pagination.pageSize,
+      orderBy: orderBy,
+    }, () => {
+      this.loadData()
+    })
+  }
+
+  render() {
+    const { value, config, options, visible, loading, total, pageIndex, pageSize, columns, placeholder } = this.state
+    
+    return <>
+      <Select
+        className="mk-pop-select"
+        showSearch={!!config.searchKey}
+        allowClear
+        value={value}
+        onSearch={(val) => val && this.searchOption(val)}
+        filterOption={false}
+        onChange={(val) => this.selectChange(val === undefined ? '' : val)}
+        disabled={config.readonly}
+        suffixIcon={<TableOutlined onClick={this.trigger}/>}
+      >
+        {options.map(option =>
+          <Select.Option disabled={option.$disabled} key={option.key} value={option.$$uuid}>{option.$label}</Select.Option>
+        )}
+      </Select>
+      <Modal
+        wrapClassName='mk-pop-select-modal'
+        title={config.label}
+        visible={visible}
+        closable={true}
+        centered={true}
+        maskClosable={false}
+        cancelText="鍏抽棴"
+        width={config.popWidth < 100 ? config.popWidth + 'vw' : config.popWidth}
+        onCancel={() => this.setState({visible: false})}
+        destroyOnClose
+      >
+        {config.searchKey ? <Search placeholder={placeholder} onSearch={this.searchOption} enterButton /> : null}
+        <Table
+          rowKey="$$uuid"
+          bordered={true}
+          rowSelection={null}
+          columns={columns}
+          dataSource={options}
+          loading={loading}
+          onRow={(record) => {
+            return {
+              className: value === record.$$uuid ? ' ant-table-row-selected ' : '',
+              onClick: () => {this.changeRow(record)},
+            }
+          }}
+          onChange={this.changeTable}
+          pagination={config.laypage === 'true' ? {
+            current: pageIndex,
+            pageSize: pageSize,
+            showSizeChanger: true,
+            total: total || 0,
+            showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+          } : false}
+        />
+      </Modal>
+    </>
+  }
+}
+
+export default MKPopSelect
\ No newline at end of file
diff --git a/src/tabviews/zshare/mutilform/mkPopSelect/index.scss b/src/tabviews/zshare/mutilform/mkPopSelect/index.scss
new file mode 100644
index 0000000..245486d
--- /dev/null
+++ b/src/tabviews/zshare/mutilform/mkPopSelect/index.scss
@@ -0,0 +1,64 @@
+.mk-pop-select {
+  .ant-select-selection__rendered {
+    margin-right: 30px;
+  }
+  .ant-select-selection__clear {
+    right: 35px;
+  }
+  .ant-select-arrow {
+    transform: translate(8px, -9px);
+    .ant-select-arrow-icon {
+      padding: 7px;
+      color: rgba(0, 0, 0, 0.25);
+      transition: color 0.2s;
+      font-size: 14px;
+      svg {
+        transition: none!important;
+        transform: none!important;
+      }
+    }
+    .ant-select-arrow-icon:hover {
+      color: var(--mk-sys-color);
+    }
+  }
+}
+.mk-pop-select-modal {
+  .ant-modal-body {
+    min-height: 200px;
+    max-height: calc(100vh - 210px);
+    overflow-y: auto;
+
+    .ant-input-search {
+      max-width: 300px;
+      margin-bottom: 20px;
+    }
+    table {
+      tr:not(.ant-table-row-selected):hover > td {
+        background-color: var(--mk-sys-color1);
+      }
+      tr.ant-table-row-selected td {
+        background-color: var(--mk-sys-color3);
+      }
+    }
+  }
+  .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);
+  }
+
+  .ant-modal-footer {
+    .ant-btn-primary {
+      display: none;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/tabviews/zshare/topSearch/index.scss b/src/tabviews/zshare/topSearch/index.scss
index 49746f8..cefe1d5 100644
--- a/src/tabviews/zshare/topSearch/index.scss
+++ b/src/tabviews/zshare/topSearch/index.scss
@@ -1,5 +1,5 @@
 .mk-search-wrap {
-  background: #ffffff;
+  // background: #ffffff;
 
   .mk-search-col {
     display: inline-block;
diff --git a/src/templates/modalconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx
index 063f651..dcd142a 100644
--- a/src/templates/modalconfig/dragelement/card.jsx
+++ b/src/templates/modalconfig/dragelement/card.jsx
@@ -1,7 +1,7 @@
 import React from 'react'
 import { useDrag, useDrop } from 'react-dnd'
 import { Select, DatePicker, Input, InputNumber, Button, Popover, Switch, Radio, Checkbox, Form, Rate } from 'antd'
-import { QuestionCircleOutlined, UploadOutlined, EditOutlined, CopyOutlined, CloseOutlined, StarFilled, FontColorsOutlined } from '@ant-design/icons'
+import { QuestionCircleOutlined, UploadOutlined, EditOutlined, CopyOutlined, CloseOutlined, StarFilled, SearchOutlined, FontColorsOutlined } from '@ant-design/icons'
 import moment from 'moment'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -80,6 +80,8 @@
     formItem = (<InputNumber value={card.initval} precision={card.decimal} />)
   } else if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link' || card.type === 'cascader') {
     formItem = (<Select value={selectval}></Select>)
+  } else if (card.type === 'popSelect') {
+    formItem = (<Select value={card.initval} suffixIcon={<SearchOutlined />}></Select>)
   } else if (card.type === 'color') {
     formItem = (<ColorSketch value={card.initval || 'transparent'}/>)
   } else if (card.type === 'date') {
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 669ef9e..5343768 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -8,7 +8,6 @@
 
 import Api from '@/api'
 import { getModalForm } from '@/templates/zshare/formconfig'
-
 import SourceElement from './dragelement/source'
 import SettingForm from './settingform'
 import MenuForm from './menuform'
@@ -348,73 +347,35 @@
 
   /**
    * @description 缂栬緫鍚庢彁浜�
-   * 1銆佽幏鍙栫紪杈戝悗鐨勮〃鍗曚俊鎭�
-   * 2銆佸幓闄ゅ彲鑳藉瓨鍦ㄧ殑绀轰緥琛ㄥ崟
-   * 3銆侀�氳繃loading鍒锋柊
    */
   handleSubmit = () => {
-    this.formRef.handleConfirm().then(res => {
-      let _config = fromJS(this.state.config).toJS()
-      let fieldrepet = false // 瀛楁閲嶅
+    let _config = fromJS(this.state.config).toJS()
 
+    this.formRef.handleConfirm(_config.fields).then(res => {
       _config.fields = _config.fields.map(item => {
-        if (item.uuid !== res.uuid && res.field && item.field && item.field.toLowerCase() === res.field.toLowerCase()) {
-          fieldrepet = true
-        }
-
-        if (item.uuid === res.uuid) {
-          if (item.style) {
-            res.style = item.style
-          }
-          return res
+        if (item.uuid === res.values.uuid) {
+          return res.values
         } else {
           return item
         }
       })
 
-      if (fieldrepet) {
-        notification.warning({
-          top: 92,
-          message: '瀛楁宸插瓨鍦紒',
-          duration: 10
-        })
-        return
-      }
-
       _config.fields = _config.fields.filter(item => !item.origin)
 
-      window.GLOB.formId = res.uuid
-
-      if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(res.type) && res.resourceType === '1' && /\s/.test(res.dataSource)) {
+      if (res.loading) {
         this.setState({
           sqlVerifing: true
         })
 
-        let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
-        ${res.dataSource}`
-
-        sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|LoginUID|SessionUid|UserID|Appkey|time_id)@/ig, `'1949-10-01 15:00:00'`)
-        
-        let rduri = ''
-        if (window.GLOB.mainSystemApi && res.database === 'sso') {
-          rduri = window.GLOB.mainSystemApi
-        }
-        
-        Api.sDebug(sql, rduri).then(result => {
-          if (result.status || result.ErrCode === '-2') {
-            this.setState({
-              sqlVerifing: false,
-              config: _config,
-              card: null,
-              visible: false
-            })
-          } else {
-            this.setState({sqlVerifing: false})
-            
-            Modal.error({
-              title: result.message
-            })
-          }
+        res.promise().then(() => {
+          this.setState({
+            sqlVerifing: false,
+            config: _config,
+            card: null,
+            visible: false
+          })
+        }, () => {
+          this.setState({sqlVerifing: false})
         })
       } else {
         this.setState({
diff --git a/src/templates/modalconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx
index b459117..4ac0090 100644
--- a/src/templates/modalconfig/settingform/index.jsx
+++ b/src/templates/modalconfig/settingform/index.jsx
@@ -5,7 +5,11 @@
 
 // import { formRule } from '@/utils/option.js'
 import StyleInput from '@/menu/stylecontroller/styleInput'
+import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
+
+const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
+const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
 
 class SettingForm extends Component {
   static propTpyes = {
@@ -18,6 +22,7 @@
     fields: null,
     display: this.props.config.setting.display || 'modal',
     placement: this.props.config.setting.placement || 'right',
+    icon: this.props.config.setting.icon || '',
     appType: sessionStorage.getItem('appType'),
     viewType: sessionStorage.getItem('editMenuType') || '',
     dialogInput: false
@@ -80,7 +85,7 @@
 
   render() {
     const { config } = this.props
-    const { fields, appType, display, placement } = this.state
+    const { fields, appType, display, placement, icon } = this.state
     const { getFieldDecorator } = this.props.form
 
     const formItemLayout = {
@@ -197,6 +202,32 @@
               )}
             </Form.Item>
           </Col> : null}
+          {appType !== 'mob' && display === 'modal' ? <Col span={12}>
+            <Form.Item label="鍥炬爣">
+              {getFieldDecorator('icon', {
+                initialValue: icon
+              })(<MkEditIcon onChange={(value) => this.setState({icon: value})} allowClear={true}/>)}
+            </Form.Item>
+          </Col> : null}
+          {appType !== 'mob' && display === 'modal' && icon ? <Col span={12}>
+            <Form.Item label="鍥炬爣鏍峰紡">
+              {getFieldDecorator('iconType', {
+                initialValue: config.setting.iconType || 'def'
+              })(
+                <Radio.Group>
+                  <Radio value="def">榛樿</Radio>
+                  <Radio value="circle">鍦嗗舰</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {appType !== 'mob' && display === 'modal' && icon ? <Col span={12}>
+            <Form.Item label="鍥炬爣棰滆壊">
+              {getFieldDecorator('iconColor', {
+                initialValue: config.setting.iconColor || ''
+              })(<ColorSketch allowClear={true}/>)}
+            </Form.Item>
+          </Col> : null}
           {appType === 'mob' && display === 'drawer' ? <Col span={12}>
             <Form.Item label={
               <Tooltip placement="topLeft" title="琛ㄥ崟鍏冪礌涓庡乏渚ц竟鐣岀殑璺濈銆�">
diff --git a/src/templates/modalconfig/settingform/index.scss b/src/templates/modalconfig/settingform/index.scss
index 01a0a3a..a6e32ec 100644
--- a/src/templates/modalconfig/settingform/index.scss
+++ b/src/templates/modalconfig/settingform/index.scss
@@ -5,4 +5,8 @@
       width: 16.5%;
     }
   }
+  .color-sketch-block {
+    position: relative;
+    top: 9px;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
index 400b7d9..2acd0d3 100644
--- a/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/searchform/index.jsx
@@ -11,9 +11,8 @@
 import './index.scss'
 
 const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
-const FieldsTable = asyncComponent(() => import('@/templates/zshare/modalform/fieldtable'))
-const DataTable = asyncComponent(() => import('@/templates/zshare/modalform/datatable'))
 const EditTable = asyncComponent(() => import('@/templates/zshare/modalform/modaleditable'))
+const FieldsTable = asyncComponent(() => import('@/templates/zshare/editTable'))
 
 const groupOptions = [
   {
@@ -190,6 +189,14 @@
       }
     } else if (type === 'checkcard') {
       reRequired.fields = false
+      reOptions.multiple = [{
+        value: 'false',
+        text: '鍗曢��'
+      }, {
+        value: 'true',
+        text: '澶氶��'
+      }]
+
       if (this.record.display === 'picture') {
         if (this.record.resourceType === '0') {        // 鑷畾涔夎祫婧�
           shows.push('options', 'fields', 'picratio')
@@ -203,6 +210,20 @@
           shows.push('dataSource', 'cardValField', 'colorField', 'fields', 'orderBy', 'orderType', 'database')
         }
       } else {
+        let appType = sessionStorage.getItem('appType')
+        if (appType === '') {
+          reOptions.multiple = [{
+            value: 'false',
+            text: '鍗曢��'
+          }, {
+            value: 'true',
+            text: '澶氶��'
+          }, {
+            value: 'dropdown',
+            text: '涓嬫媺鑿滃崟'
+          }]
+        }
+
         reRequired.fields = true
         if (this.record.resourceType === '0') {        // 鑷畾涔夎祫婧�
           shows.push('options', 'fields', 'selectStyle', 'border')
@@ -349,6 +370,9 @@
         this.record.match = 'like'
         _fieldval.match = 'like'
       }
+    } else if (key === 'display') {
+      this.record.multiple = 'false'
+      _fieldval.multiple = 'false'
     } else if (key === 'items') {
       let _initval = this.props.form.getFieldValue('initval')
       if (_initval && !value.includes(_initval[0])) {
@@ -552,12 +576,44 @@
         let type = this.record.type
         
         if (type !== 'checkcard') {
-          content = <EditTable type={type} module="search" transfield={{}} linkSubFields={[]} onChange={this.changeOptions}/>
+          let columns = []
+
+          if (type === 'link') {
+            columns.push({ title: 'ParentID', key: 'ParentID', strict: true })
+          }
+
+          columns.push({ title: 'Value', key: 'Value', strict: true })
+          columns.push({ title: 'Text', key: 'Text' })
+
+          content = <EditTable columns={columns} module="search" onChange={this.changeOptions}/>
         } else {
           if (this.record.linkField) {
             type = 'link'
           }
-          content = <DataTable type={type} multiple={this.record.multiple} display={this.record.display} linkSubFields={[]} transfield={{}} fields={this.record.fields || []} onChange={this.changeOptions}/>
+
+          let columns = []
+          let fields = this.record.fields || []
+          let keys = ['ParentID', 'pid']
+
+          if (type === 'link') {
+            columns.push({ title: 'ParentID', key: 'ParentID', strict: true })
+          } else if (this.record.multiple === 'dropdown' && this.record.display === 'text') {
+            columns.push({ title: 'pid', key: 'pid', strict: true })
+          }
+          columns.push({ title: 'Value', key: '$value', strict: true })
+
+          if (this.record.display === 'picture') {
+            columns.push({ title: 'url', key: '$url', type: 'file' })
+          } else if (this.record.display === 'color') {
+            columns.push({ title: 'Color', key: '$color' })
+          }
+
+          fields.forEach(item => {
+            keys.push(item.field)
+            columns.push({ title: item.field, key: item.field })
+          })
+
+          content = <EditTable columns={columns} onChange={this.changeOptions}/>
         }
       } else if (item.type === 'fields') {
         span = 24
@@ -567,7 +623,7 @@
           { required: item.required, message: '璇锋坊鍔�' + item.label + '!' }
         ]
 
-        content = <FieldsTable onChange={this.changeField}/>
+        content = <FieldsTable indexShow={false} actions={['edit', 'move', 'del', 'add']} columns={item.columns} data={this.record.fields || []} onChange={this.changeField}/>
       } else if (item.type === 'checkbox') {
         rules = [
           { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index 60dd750..24902d3 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -3,7 +3,7 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
 import { Table, Input, InputNumber, Popconfirm, Form, Select, Radio, Cascader, notification, message, Modal, Typography } from 'antd'
-import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined } from '@ant-design/icons'
+import { CopyOutlined, EditOutlined, DeleteOutlined, SwapOutlined, PlusOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
 import ColorSketch from '@/mob/colorsketch'
@@ -258,6 +258,7 @@
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
+
     if (!is(fromJS(this.state.data), fromJS(nextProps.data))) {
       this.setState({data: nextProps.data, editingKey: ''})
     } else if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
@@ -518,6 +519,26 @@
       return
     }
 
+    let forbid = false
+
+    columns.forEach(col => {
+      if (!col.forbids || forbid) return
+
+      let key = record[col.dataIndex].toLowerCase()
+      if (col.forbids.includes(key)) {
+        forbid = col.title + '涓嶅彲浣跨敤' + record[col.dataIndex]
+      }
+    })
+
+    if (forbid) {
+      notification.warning({
+        top: 92,
+        message: forbid,
+        duration: 5
+      })
+      return
+    }
+
     let unique = true
     columns.forEach(col => {
       if (col.unique !== true || !unique) return
@@ -582,6 +603,26 @@
         row = {...newData[index], ...row}
       } else {
         row.uuid = uuid
+      }
+
+      let forbid = false
+
+      columns.forEach(col => {
+        if (!col.forbids || forbid) return
+
+        let key = row[col.dataIndex].toLowerCase()
+        if (col.forbids.includes(key)) {
+          forbid = col.title + '涓嶅彲浣跨敤' + row[col.dataIndex]
+        }
+      })
+
+      if (forbid) {
+        notification.warning({
+          top: 92,
+          message: forbid,
+          duration: 5
+        })
+        return
       }
 
       let unique = true
@@ -652,6 +693,37 @@
     })
   }
 
+  handleAdd = () => {
+    const { columns } = this.props
+    const { data } = this.state
+
+    let _index = data.length + 1
+    let item = {
+      uuid: Utils.getuuid()
+    }
+
+    columns.forEach(col => {
+      if (!col.dataIndex) return
+
+      item[col.dataIndex] = col.initval || ''
+
+      if (col.unique) {
+        while (data.filter(cell => cell[col.dataIndex] === item[col.dataIndex]).length > 0) {
+          _index++
+          item[col.dataIndex] = col.initval + _index
+        }
+      }
+    })
+
+    let _data = [...data, item]
+
+    this.setState({
+      data: _data
+    }, () => {
+      this.props.onChange(_data)
+    })
+  }
+
   render() {
     const { actions, indexShow, searchKey } = this.props
     const { editLineId } = this.state
@@ -714,6 +786,7 @@
     return (
       <EditableContext.Provider value={this.props.form}>
         <div className="modal-edit-table">
+          {actions.includes('add') ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
           <DndProvider>
             <Table
               bordered
diff --git a/src/templates/zshare/editTable/index.scss b/src/templates/zshare/editTable/index.scss
index cac8205..564dc79 100644
--- a/src/templates/zshare/editTable/index.scss
+++ b/src/templates/zshare/editTable/index.scss
@@ -4,6 +4,7 @@
       position: absolute;
       font-size: 12px;
       margin-top: -4px;
+      white-space: nowrap;
     }
     .color-sketch-block {
       width: 200px;
@@ -112,5 +113,17 @@
       color: #ff4d4f;
     }
   }
+  .ant-typography {
+    margin: 3px 0px;
+  }
+  .add-row {
+    position: absolute;
+    z-index: 1;
+    right: 10px;
+    top: -30px;
+    padding: 5px;
+    font-size: 18px;
+    color: #26C281;
+  }
 }
 
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index f2373e3..6e13fc6 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -1,3 +1,4 @@
+import React from 'react'
 import { formRule, btnClasses } from '@/utils/option.js'
 
 /**
@@ -549,18 +550,80 @@
       }]
     },
     {
-      type: 'fields',
-      key: 'fields',
-      label: '瀛楁闆�',
-      initVal: card.fields || [],
-      required: true
-    },
-    {
       type: 'codemirror',
       key: 'dataSource',
       label: '鏁版嵁婧�',
       initVal: card.dataSource || '',
+      tooltip: '鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'',
       required: true
+    },
+    {
+      type: 'fields',
+      key: 'fields',
+      label: '瀛楁闆�',
+      initVal: card.fields || [],
+      required: true,
+      columns: [
+        {
+          title: '瀛楁鍚�',
+          dataIndex: 'field',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          strict: true,
+          forbids: ['value', 'parentid', 'pid'],
+          initval: 'field',
+          rules: [{
+            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
+            message: '璇蜂娇鐢ㄦ暟瀛椼�佸瓧姣嶃�佹眽瀛椾互鍙奯-'
+          }],
+          width: '20%'
+        },
+        {
+          title: '瀛椾綋棰滆壊',
+          dataIndex: 'color',
+          inputType: 'color',
+          editable: true,
+          initval: 'rgba(0, 0, 0, 0.85)',
+          width: '20%',
+          render: (text, record) => {
+            return <span style={{color: text}}>绀轰緥</span>
+          }
+        },
+        {
+          title: '瀛椾綋澶у皬',
+          dataIndex: 'fontSize',
+          inputType: 'number',
+          min: 12,
+          max: 50,
+          editable: true,
+          initval: 14,
+          width: '20%',
+        },
+        {
+          title: '瀵归綈鏂瑰紡',
+          dataIndex: 'align',
+          inputType: 'select',
+          editable: true,
+          width: '20%',
+          initval: 'left',
+          options: [
+            {value: 'left', text: '灞呭乏'},
+            {value: 'center', text: '灞呬腑'},
+            {value: 'right', text: '灞呭彸'},
+            // {value: 'justify', text: 'justify'}
+          ],
+          render: (text, record) => {
+            if (text === 'center') {
+              return '灞呬腑'
+            } else if (text === 'right') {
+              return '灞呭彸'
+            } else {
+              return '灞呭乏'
+            }
+          }
+        }
+      ]
     },
     {
       type: 'options',
@@ -644,7 +707,7 @@
       required: false
     },
     {
-      type: 'select',
+      type: 'radio',
       key: 'orderType',
       label: '鎺掑簭鏂瑰紡',
       initVal: card.orderType || 'asc',
@@ -2567,6 +2630,9 @@
     value: 'link',
     text: '鑱斿姩鑿滃崟'
   }, {
+    value: 'popSelect',
+    text: '閫夋嫨鍣�'
+  }, {
     value: 'switch',
     text: '寮�鍏�'
   }, {
@@ -2904,12 +2970,210 @@
     //   }]
     // },
     {
+      type: 'codemirror',
+      key: 'dataSource',
+      label: '鏁版嵁婧�',
+      initVal: card.dataSource || '',
+      tooltip: '鏁版嵁鏉冮檺鏇挎崲绗� $@ -> /* 鎴� \'\'銆� @$ -> */ 鎴� \'\'',
+      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@ID@銆丂BID@銆�',
+      required: true,
+      readonly: false
+    },
+    {
       type: 'fields',
       key: 'fields',
       label: '瀛楁闆�',
       initVal: card.fields || [],
       required: true,
-      readonly: false
+      readonly: false,
+      columns: [
+        {
+          title: '瀛楁鍚�',
+          dataIndex: 'field',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          strict: true,
+          forbids: ['value', 'parentid', 'pid'],
+          initval: 'field',
+          rules: [{
+            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
+            message: '璇蜂娇鐢ㄦ暟瀛椼�佸瓧姣嶃�佹眽瀛椾互鍙奯-'
+          }],
+          width: '20%'
+        },
+        {
+          title: '瀛椾綋棰滆壊',
+          dataIndex: 'color',
+          inputType: 'color',
+          editable: true,
+          initval: 'rgba(0, 0, 0, 0.85)',
+          width: '20%',
+          render: (text, record) => {
+            return <span style={{color: text}}>绀轰緥</span>
+          }
+        },
+        {
+          title: '瀛椾綋澶у皬',
+          dataIndex: 'fontSize',
+          inputType: 'number',
+          min: 12,
+          max: 50,
+          editable: true,
+          initval: 14,
+          width: '20%',
+        },
+        {
+          title: '瀵归綈鏂瑰紡',
+          dataIndex: 'align',
+          inputType: 'select',
+          editable: true,
+          width: '20%',
+          initval: 'left',
+          options: [
+            {value: 'left', text: '灞呭乏'},
+            {value: 'center', text: '灞呬腑'},
+            {value: 'right', text: '灞呭彸'},
+            // {value: 'justify', text: 'justify'}
+          ],
+          render: (text, record) => {
+            if (text === 'center') {
+              return '灞呬腑'
+            } else if (text === 'right') {
+              return '灞呭彸'
+            } else {
+              return '灞呭乏'
+            }
+          }
+        }
+      ]
+    },
+    {
+      type: 'fields',
+      key: 'columns',
+      label: '瀛楁闆�',
+      initVal: card.columns || [],
+      required: true,
+      readonly: false,
+      columns: [
+        {
+          title: '鍚嶇О',
+          dataIndex: 'label',
+          inputType: 'input',
+          editable: true,
+          initval: 'label',
+          width: '20%'
+        },
+        {
+          title: '瀛楁',
+          dataIndex: 'field',
+          inputType: 'input',
+          editable: true,
+          unique: true,
+          strict: true,
+          copy: true,
+          initval: 'field',
+          rules: [{
+            pattern: /^[\u4E00-\u9FA50-9a-zA-Z_-]*$/ig,
+            message: '璇蜂娇鐢ㄦ暟瀛椼�佸瓧姣嶃�佹眽瀛椾互鍙奯-'
+          }],
+          width: '20%'
+        },
+        {
+          title: '闅愯棌',
+          dataIndex: 'Hide',
+          inputType: 'radio',
+          editable: true,
+          width: '20%',
+          initval: 'false',
+          options: [
+            {value: 'true', text: '鏄�'},
+            {value: 'false', text: '鍚�'},
+          ],
+          render: (text, record) => {
+            if (text === 'true') {
+              return '鏄�'
+            } else {
+              return '鍚�'
+            }
+          }
+        },
+        {
+          title: '鎺掑簭',
+          dataIndex: 'IsSort',
+          inputType: 'radio',
+          editable: true,
+          width: '20%',
+          initval: 'false',
+          options: [
+            {value: 'true', text: '鏄�'},
+            {value: 'false', text: '鍚�'},
+          ],
+          render: (text, record) => {
+            if (text === 'true') {
+              return '鏄�'
+            } else {
+              return '鍚�'
+            }
+          }
+        }
+      ]
+    },
+    {
+      type: 'select',
+      key: 'primaryKey',
+      label: '涓婚敭',
+      initVal: card.primaryKey || '',
+      required: true,
+      readonly: false,
+      options: 'columns'
+    },
+    {
+      type: 'text',
+      key: 'order',
+      label: '榛樿鎺掑簭',
+      initVal: card.order || '',
+      placeholder: 'ID asc',
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'showField',
+      label: '鏄剧ず瀛楁',
+      initVal: card.showField || '',
+      tooltip: '鐢ㄤ簬鎺у埗閫夋嫨妗嗕腑鐨勬樉绀哄唴瀹广��',
+      required: true,
+      options: 'columns'
+    },
+    {
+      type: 'select',
+      key: 'controlField',
+      label: '绂佺敤瀛楁',
+      initVal: card.controlField || '',
+      tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆傚瓧娈靛�间负true鏃讹紝閫夐」涓嶅彲閫夈��',
+      required: false,
+      allowClear: true,
+      options: 'columns'
+    },
+    {
+      type: 'text',
+      key: 'searchKey',
+      label: '鎼滅储瀛楁',
+      initVal: card.searchKey || '',
+      tooltip: '澶氫釜鍊艰鐢ㄩ�楀彿鍒嗛殧銆�',
+      required: false,
+      rules: [{
+        pattern: /^[0-9a-zA-Z,_-]*$/ig,
+        message: '瀛楁鍚嶅彧鍏佽鍖呭惈鏁板瓧銆佸瓧姣嶄互鍙奯-',
+      }]
+    },
+    {
+      type: 'number',
+      key: 'popWidth',
+      label: '寮圭獥瀹藉害',
+      initVal: card.popWidth || 60,
+      tooltip: '灏忎簬100鏃朵负鐧惧垎鐜囷紝澶т簬100鏃朵负缁濆鍊笺��',
+      required: true
     },
     {
       type: 'options',
@@ -2920,13 +3184,33 @@
       readonly: false
     },
     {
-      type: 'codemirror',
-      key: 'dataSource',
-      label: '鏁版嵁婧�',
-      initVal: card.dataSource || '',
-      placeholder: '绯荤粺鍙橀噺锛歮k_departmentcode銆乵k_organization銆乵k_user_type銆傚叕鍏卞�硷細@ID@銆丂BID@銆�',
-      required: true,
-      readonly: false
+      type: 'radio',
+      key: 'laypage',
+      label: '鍒嗛〉',
+      initVal: card.laypage || 'true',
+      required: false,
+      options: [{
+        value: 'true',
+        text: '鏄�'
+      }, {
+        value: 'false',
+        text: '鍚�'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'onload',
+      label: '鍒濆鍖�',
+      initVal: card.onload || 'true',
+      tooltip: '褰撴病鏈夎缃悳绱㈠瓧娈垫椂锛屽垵濮嬪寲鍔犺浇鏁版嵁銆�',
+      required: false,
+      options: [{
+        value: 'true',
+        text: '鍔犺浇'
+      }, {
+        value: 'false',
+        text: '涓嶅姞杞�'
+      }]
     },
     {
       type: 'radio',
@@ -2985,7 +3269,7 @@
       readonly: false
     },
     {
-      type: 'select',
+      type: 'radio',
       key: 'orderType',
       label: '鎺掑簭鏂瑰紡',
       initVal: card.orderType || 'asc',
@@ -4016,7 +4300,11 @@
       initVal: card.regularExtra || '',
       tooltip: '姝e垯楠岃瘉鏃跺厑璁告坊鍔犵殑鑷畾涔夊瓧绗︼紝鍖呮嫭~!@#$%^&*()_+:;{}<>,.-',
       required: false,
-      readonly: false
+      readonly: false,
+      rules: [{
+        pattern: /^[~!@#$%^&*()_+:;{}<>,.-]*$/,
+        message: '鎵╁睍绗﹀寘鎷瑍!@#$%^&*()_+:;{}<>,.-'
+      }]
     },
     {
       type: 'text',
diff --git a/src/templates/zshare/modalform/datatable/index.jsx b/src/templates/zshare/modalform/datatable/index.jsx
deleted file mode 100644
index 8f3e62b..0000000
--- a/src/templates/zshare/modalform/datatable/index.jsx
+++ /dev/null
@@ -1,502 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { DndProvider, DragSource, DropTarget } from 'react-dnd'
-import { Table, Input, Popconfirm, Form, notification, message } from 'antd'
-import { PlusOutlined, EditOutlined, DeleteOutlined, SwapOutlined } from '@ant-design/icons'
-
-import Utils from '@/utils/utils.js'
-import asyncComponent from '@/utils/asyncComponent'
-// import FileUpload from '@/tabviews/zshare/fileupload'
-import './index.scss'
-
-const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
-const EditableContext = React.createContext()
-let dragingIndex = -1
-
-class BodyRow extends React.Component {
-  render() {
-    const { isOver, moveAble, connectDragSource, connectDropTarget, moveRow, ...restProps } = this.props
-    let { className } = restProps
-
-    if (isOver && moveAble) {
-      if (restProps.index > dragingIndex) {
-        className += ' drop-over-downward'
-      }
-      if (restProps.index < dragingIndex) {
-        className += ' drop-over-upward'
-      }
-    }
-
-    if (moveAble) {
-      return connectDragSource(
-        connectDropTarget(<tr {...restProps} className={className} style={{...restProps.style, cursor: 'move'}} />),
-      )
-    } else {
-      return (<tr {...restProps} className={className} style={restProps.style} />)
-    }
-  }
-}
-
-const rowSource = {
-  beginDrag(props) {
-    dragingIndex = props.index
-    return {
-      index: props.index,
-    }
-  }
-}
-
-const rowTarget = {
-  drop(props, monitor) {
-    const dragIndex = monitor.getItem().index
-    const hoverIndex = props.index
-
-    if (dragIndex === hoverIndex) {
-      return
-    }
-
-    props.moveRow(dragIndex, hoverIndex)
-
-    monitor.getItem().index = hoverIndex
-  },
-}
-
-const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
-  connectDropTarget: connect.dropTarget(),
-  isOver: monitor.isOver(),
-}))(
-  DragSource('row', rowSource, connect => ({
-    connectDragSource: connect.dragSource(),
-  }))(BodyRow),
-)
-
-class EditableCell extends Component {
-  getInput = (form) => {
-    const { inputType, record } = this.props
-    if (inputType === 'file') {
-      return <SourceComponent initialValue={record ? (record.$url || '') : ''} type="" placement="right"/>
-      // return <FileUpload config={{
-      //   initval: record ? (record.$url || '') : '',
-      //   suffix: '',
-      //   maxfile: 1,
-      //   fileType: 'picture-card'
-      // }}/>
-    } else {
-      return <Input onPressEnter={() => this.getValue(form)} />
-    }
-  }
-
-  getValue = (form) => {
-    const { record } = this.props
-    form.validateFields((error, row) => {
-      if (error) {
-        return
-      }
-
-      this.props.onSave({...record, ...row})
-    })
-  }
-
-  renderCell = (form) => {
-    const { getFieldDecorator } = form
-    const {
-      editing,
-      dataIndex,
-      title,
-      record,
-      inputType,
-      index,
-      children,
-      onSave,
-      ...restProps
-    } = this.props;
-
-    let _val = ''
-
-    if (record && dataIndex) {
-      _val = record[dataIndex]
-    }
-
-    return (
-      <td {...restProps}>
-        {editing ? (
-          <Form.Item style={{ margin: '0 -5px 0 -5px' }}>
-            {getFieldDecorator(dataIndex, {
-              // rules: [
-              //   {
-              //     required: dataIndex === '$value',
-              //     message: `Please Input ${title}!`,
-              //   },
-              // ],
-              initialValue: _val,
-            })(this.getInput(form))}
-          </Form.Item>
-        ) : (
-          children
-        )}
-      </td>
-    )
-  }
-
-  render() {
-    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
-  }
-}
-
-class EdiDataTable extends Component {
-  static propTpyes = {
-    transfield: PropTypes.object,   // 瀛楁鍚嶇О
-    type: PropTypes.string,         // 鏄惁涓哄叧鑱旇〃鍗�
-    display: PropTypes.string,      // 鏁版嵁绫诲瀷锛屾枃鏈�佸浘鐗�
-    fields: PropTypes.array,        // 瀛楁闆�
-    linkSubFields: PropTypes.array, // 濉厖瀛楁
-    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
-  }
-
-  UNSAFE_componentWillMount () {
-    let data = this.props['data-__meta'].initialValue
-
-    this.setState({
-      data: data,
-      columns: this.getCloumns()
-    })
-  }
-
-  state = {
-    data: [],
-    editingKey: '',
-    columns: []
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (
-      !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
-      !is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) ||
-      this.props.display !== nextProps.display ||
-      (nextProps.multiple && this.props.multiple !== nextProps.multiple) ||
-      this.props.type !== nextProps.type
-    ) {
-      this.setState({editingKey: ''}, () => {
-        this.setState({
-          columns: this.getCloumns()
-        })
-      })
-    }
-  }
-
-  getCloumns = () => {
-    const { display, fields, linkSubFields, transfield, type, multiple } = this.props
-    let columns = []
-    let keys = ['ParentID', 'pid']
-
-    if (display === 'picture') {
-      columns.push({
-        title: 'url',
-        dataIndex: '$url',
-        inputType: 'file',
-        // width: '40%',
-        editable: true,
-        render: (text) => {
-          if (!text) return ''
-          return <span style={{display: 'block', width: '70px', height: '70px'}}><img style={{width: '100%', height: '100%'}} src={text} alt="" /></span>
-        }
-      })
-    } else if (display === 'color') {
-      columns.push({
-        title: 'Color',
-        dataIndex: '$color',
-        inputType: 'text',
-        editable: true,
-        render: (text) => {
-          if (!text) return ''
-          return <div style={{height: '20px', background: text}}></div>
-        }
-      })
-    }
-
-    fields.forEach(item => {
-      keys.push(item.field)
-      columns.push({
-        title: item.field,
-        dataIndex: item.field,
-        editable: true,
-      })
-    })
-
-    if (linkSubFields.length > 0) {
-      linkSubFields.forEach(m => {
-        if (keys.includes(m)) return
-
-        columns.push({
-          title: transfield[m] || m,
-          dataIndex: m,
-          editable: true,
-        })
-      })
-    }
-    
-    columns.unshift({
-      title: 'Value',
-      dataIndex: '$value',
-      editable: true,
-    })
-
-    if (multiple === 'dropdown' && display === 'text') {
-      columns.unshift({
-        title: 'pid',
-        dataIndex: 'pid',
-        editable: true,
-      })
-    }
-
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        editable: true,
-      })
-    }
-
-    columns.push({
-      title: '鎿嶄綔',
-      dataIndex: 'operation',
-      align: 'center',
-      width: '18%',
-      render: (text, record) => {
-        const { editingKey } = this.state
-        const editable = this.isEditing(record)
-        return editable ? (
-          <span>
-            <EditableContext.Consumer>
-              {form => (
-                <span onClick={() => this.save(form, record.key)} style={{ marginRight: 8 , color: '#1890ff', cursor: 'pointer'}}>
-                  淇濆瓨
-                </span>
-              )}
-            </EditableContext.Consumer>
-            <span style={{ color: '#1890ff', cursor: 'pointer'}} onClick={() => this.cancel(record.key)}>鍙栨秷</span>
-          </span>
-        ) : (
-          <div className={'operation-btn' + (editingKey !== '' ? ' disabled' : '')}>
-            <span className="primary" onClick={() => {editingKey === '' && this.edit(record.key)}}><EditOutlined /></span>
-            <span className="hide-control" title="鏄剧ず/闅愯棌" onClick={() => {editingKey === '' && this.handleHide(record.key)}}><SwapOutlined /></span>
-            {editingKey === '' ? <Popconfirm
-              overlayClassName="popover-confirm"
-              title="纭畾鍒犻櫎鍚�?"
-              onConfirm={() => this.handleDelete(record.key)
-            }>
-              <span className="danger"><DeleteOutlined /></span>
-            </Popconfirm> : null}
-            {editingKey !== '' ? <span className="danger"><DeleteOutlined /></span> : null}
-          </div>
-        )
-      }
-    })
-    
-    return columns
-  }
-
-  isEditing = record => record.key === this.state.editingKey
-
-  cancel = () => {
-    this.setState({ editingKey: '' })
-  }
-
-  onSave = (record) => {
-    const { type } = this.props
-    const newData = [...this.state.data]
-    const index = newData.findIndex(item => record.key === item.key)
-
-    if (type === 'link') {
-      if (newData.filter(m => record.key !== m.key && record.$value === m.$value && record.ParentID === m.ParentID).length > 0) {
-        message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
-      }
-    } else {
-      if (newData.filter(m => record.key !== m.key && record.$value === m.$value).length > 0) {
-        message.warning('姝alue鍊煎凡瀛樺湪锛�')
-      }
-    }
-
-    if (index > -1) {
-      newData.splice(index, 1, record)
-      this.setState({ data: newData, editingKey: '' }, () => {
-        this.props.onChange(newData)
-      })
-    }
-  }
-
-  handleDelete = (key) => {
-    const { data } = this.state
-    let _data = data.filter(item => key !== item.key)
-
-    this.setState({
-      data: _data
-    }, () => {
-      this.props.onChange(_data)
-    })
-  }
-
-  save(form, key) {
-    const { type } = this.props
-
-    form.validateFields((error, row) => {
-      if (error) {
-        return;
-      }
-
-      const newData = [...this.state.data]
-      const index = newData.findIndex(item => key === item.key)
-
-      if (type === 'link') {
-        if (newData.filter(m => key !== m.key && row.$value === m.$value && row.ParentID === m.ParentID).length > 0) {
-          message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
-        }
-      } else {
-        if (newData.filter(m => key !== m.key && row.$value === m.$value).length > 0) {
-          message.warning('姝alue鍊煎凡瀛樺湪锛�')
-        }
-      }
-
-      if (index > -1) {
-        const item = newData[index]
-        newData.splice(index, 1, {
-          ...item,
-          ...row,
-        })
-        this.setState({ data: newData, editingKey: '' }, () => {
-          this.props.onChange(newData)
-        })
-      } else {
-        newData.push(row);
-        this.setState({ data: newData, editingKey: '' }, () => {
-          this.props.onChange(newData)
-        })
-      }
-    })
-  }
-
-  handleAdd = () => {
-    const { fields, display } = this.props
-    if (this.state.data.length >= 100) {
-      notification.warning({
-        top: 92,
-        message: '鏈�澶氬彲娣诲姞100椤癸紒',
-        duration: 5
-      })
-      return
-    }
-
-    let item = { key: Utils.getuuid(), $value: `${this.state.data.length + 1}`, ParentID: '' }
-
-    if (display === 'picture') {
-      item.$url = ''
-    } else if (display === 'color') {
-      item.$color = ''
-    }
-
-    fields.forEach(f => {
-      item[f.field] = `${this.state.data.length + 1}`
-    })
-
-    let data = [...this.state.data, item]
-
-    this.setState({ data, editingKey: '' }, () => {
-      this.props.onChange(data)
-    })
-  }
-
-  edit(key) {
-    this.setState({ editingKey: key })
-  }
-
-  handleHide = (key) => {
-    let _data = this.state.data.map(item => {
-      if (item.key === key) {
-        item.Hide = !item.Hide
-      }
-      return item
-    })
-    this.setState({
-      data: _data
-    }, () => {
-      this.props.onChange(_data)
-    })
-  }
-
-  moveRow = (dragIndex, hoverIndex) => {
-    const { editingKey } = this.state
-    let _data = fromJS(this.state.data).toJS()
-
-    if (editingKey) return
-
-    _data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
-
-    this.setState({
-      data: _data
-    }, () => {
-      this.props.onChange(_data)
-    })
-  }
-
-  render() {
-    const { display, fields } = this.props
-
-    const components = {
-      body: {
-        row: DragableBodyRow,
-        cell: EditableCell
-      }
-    }
-
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          dataIndex: col.dataIndex,
-          inputType: col.inputType,
-          title: col.title,
-          editing: this.isEditing(record),
-          onSave: this.onSave,
-        }),
-      }
-    })
-
-    let addable = false
-    if (display === 'picture' || display === 'color') {
-      addable = true
-    } else if (fields && fields.length > 0) {
-      addable = true
-    }
-
-    return (
-      <EditableContext.Provider value={this.props.form}>
-        <div className="modal-card-data-table">
-          {addable ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
-          <DndProvider>
-            <Table
-              components={components}
-              bordered
-              rowKey="key"
-              dataSource={this.state.data}
-              columns={columns}
-              rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
-              onRow={(record, index) => ({
-                index,
-                moveAble: !this.state.editingKey,
-                moveRow: this.moveRow,
-              })}
-              pagination={false}
-            />
-          </DndProvider>
-        </div>
-      </EditableContext.Provider>
-    )
-  }
-}
-
-export default Form.create()(EdiDataTable)
\ No newline at end of file
diff --git a/src/templates/zshare/modalform/datatable/index.scss b/src/templates/zshare/modalform/datatable/index.scss
deleted file mode 100644
index ac76a17..0000000
--- a/src/templates/zshare/modalform/datatable/index.scss
+++ /dev/null
@@ -1,88 +0,0 @@
-.modal-card-data-table {
-  .add-row {
-    position: absolute;
-    z-index: 1;
-    right: 10px;
-    top: -30px;
-    padding: 5px;
-    font-size: 18px;
-    color: #26C281;
-  }
-  .editable-row {
-    .ant-form-explain {
-      position: absolute;
-      font-size: 12px;
-      margin-top: -4px;
-    }
-    .ant-form-item-control {
-      line-height: 1;
-    }
-    > td {
-      padding: 13px 10px;
-      word-break: break-all;
-    }
-    .fileupload-form-container .ant-upload-list-picture-card .ant-upload-list-item {
-      margin: 0;
-      padding: 2px;
-      .ant-upload-list-item-info > span {
-        height: 100%;
-      }
-    }
-    .ant-input {
-      padding: 0 5px;
-    }
-  }
-  .editable-row.hide {
-    td:not(:last-child) {
-      text-decoration: line-through;
-    }
-  }
-  .operation-btn {
-    font-size: 16px;
-    text-align: center;
-    span {
-      margin-right: 20px;
-      cursor: pointer;
-    }
-    span:last-child {
-      margin-right: 0px;
-    }
-    .primary {
-      color: #1890ff;
-    }
-    .hide-control {
-      color: rgb(142, 68, 173);
-    }
-    .danger {
-      color: #ff4d4f;
-    }
-  }
-  .operation-btn.disabled {
-    span {
-      cursor: default;
-    }
-    .primary {
-      color: rgba(0, 0, 0, .25);
-    }
-    .hide-control {
-      color: rgba(0, 0, 0, .25);
-    }
-    .danger {
-      color: rgba(0, 0, 0, .25);
-    }
-  }
-  tr.drop-over-downward td {
-    border-bottom: 2px dashed #1890ff;
-  }
-  tr.drop-over-upward td {
-    border-top: 2px dashed #1890ff;
-  }
-  .mk-source-wrap {
-    .ant-radio-button-wrapper + .ant-radio-button-wrapper {
-      border-radius: 0 4px 4px 0;
-    }
-    .ant-radio-button-wrapper:last-child {
-      display: none;
-    }
-  }
-}
diff --git a/src/templates/zshare/modalform/fieldtable/index.jsx b/src/templates/zshare/modalform/fieldtable/index.jsx
deleted file mode 100644
index 3b607cf..0000000
--- a/src/templates/zshare/modalform/fieldtable/index.jsx
+++ /dev/null
@@ -1,169 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { notification } from 'antd'
-import { PlusOutlined } from '@ant-design/icons'
-
-import asyncComponent from '@/utils/asyncComponent'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const EditTable = asyncComponent(() => import('@/templates/zshare/editTable'))
-
-class EdiFieldsTable extends Component {
-  static propTpyes = {
-    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
-  }
-
-  UNSAFE_componentWillMount () {
-    let data = this.props['data-__meta'].initialValue || []
-
-    this.setState({
-      loading: false,
-      data: data.map(item => {
-        item.uuid = item.uuid || item.key
-        return item
-      })
-    })
-  }
-
-  state = {
-    data: [],
-    columns: [
-      {
-        title: '瀛楁鍚�',
-        dataIndex: 'field',
-        inputType: 'input',
-        editable: true,
-        width: '20%',
-      },
-      {
-        title: '瀛椾綋棰滆壊',
-        dataIndex: 'color',
-        inputType: 'color',
-        editable: true,
-        width: '20%',
-        render: (text, record) => {
-          return <span style={{color: text}}>绀轰緥</span>
-        }
-      },
-      {
-        title: '瀛椾綋澶у皬',
-        dataIndex: 'fontSize',
-        inputType: 'number',
-        min: 12,
-        max: 50,
-        editable: true,
-        width: '20%',
-      },
-      {
-        title: '瀵归綈鏂瑰紡',
-        dataIndex: 'align',
-        inputType: 'select',
-        editable: true,
-        width: '20%',
-        options: [
-          {value: 'left', text: '灞呭乏'},
-          {value: 'center', text: '灞呬腑'},
-          {value: 'right', text: '灞呭彸'},
-          // {value: 'justify', text: 'justify'}
-        ],
-        render: (text, record) => {
-          if (text === 'center') {
-            return '灞呬腑'
-          } else if (text === 'right') {
-            return '灞呭彸'
-          } else {
-            return '灞呭乏'
-          }
-        }
-      }
-    ]
-  }
-
-  handleAdd = () => {
-    let _index = this.state.data.length + 1
-    let item = {
-      key: Utils.getuuid(),
-      field: `field${_index}`,
-      color: 'rgba(0, 0, 0, 0.85)',
-      align: 'left',
-      fontSize: 14,
-    }
-
-    item.uuid = item.key
-
-    while (this.state.data.filter(cell => cell.field === item.field).length > 0) {
-      _index++
-      item.field = `field${_index}`
-    }
-
-    let data = [...this.state.data, item]
-
-    this.setState({ data }, () => {
-      this.props.onChange(data)
-    })
-  }
-
-  changeData = (data) => {
-    let fields = data.map(cell => cell.field)
-    fields = Array.from(new Set(fields))
-    if (data.length > 1 && data.length > fields.length) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁鍚嶄笉鍙噸澶嶏紒',
-        duration: 5
-      })
-      this.setState({loading: true}, () => {
-        this.setState({loading: false})
-      })
-      return
-    } else if (fields.filter(f => f.toLowerCase() === 'value').length > 0) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁鍚嶄笉鍙娇鐢╲alue锛�',
-        duration: 5
-      })
-      this.setState({loading: true}, () => {
-        this.setState({loading: false})
-      })
-      return
-    } else if (fields.filter(f => f.toLowerCase() === 'parentid').length > 0) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁鍚嶄笉鍙娇鐢╬arentid锛�',
-        duration: 5
-      })
-      this.setState({loading: true}, () => {
-        this.setState({loading: false})
-      })
-      return
-    } else if (fields.filter(f => f.toLowerCase() === 'pid').length > 0) {
-      notification.warning({
-        top: 92,
-        message: '瀛楁鍚嶄笉鍙娇鐢╬id锛�',
-        duration: 5
-      })
-      this.setState({loading: true}, () => {
-        this.setState({loading: false})
-      })
-      return
-    }
-
-    this.setState({ data }, () => {
-      this.props.onChange(data)
-    })
-  }
-
-  render() {
-    const { data, columns, loading } = this.state
-
-    return (
-      <div className="modal-card-field-table">
-        {data.length < 6 ? <PlusOutlined className="add-row" onClick={this.handleAdd} /> : null}
-        {!loading ? <EditTable indexShow={false} actions={['edit', 'move', 'del']} data={data} columns={columns} onChange={this.changeData}/> : null}
-      </div>
-    )
-  }
-}
-
-export default EdiFieldsTable
\ No newline at end of file
diff --git a/src/templates/zshare/modalform/fieldtable/index.scss b/src/templates/zshare/modalform/fieldtable/index.scss
deleted file mode 100644
index 6e9832a..0000000
--- a/src/templates/zshare/modalform/fieldtable/index.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-.modal-card-field-table {
-  .add-row {
-    position: absolute;
-    z-index: 1;
-    right: 10px;
-    top: -30px;
-    padding: 5px;
-    font-size: 18px;
-    color: #26C281;
-  }
-  .ant-empty {
-    margin: 0;
-  }
-}
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 43d8efa..0c6a6b7 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -1,9 +1,10 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
-import { Form, Row, Col, Input, Select, Radio, notification, InputNumber, Tooltip, Checkbox, AutoComplete } from 'antd'
+import { Form, Row, Col, Input, Select, Radio, notification, InputNumber, Tooltip, Checkbox, AutoComplete, Modal } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
+import Api from '@/api'
 import { formRule } from '@/utils/option.js'
 import { dateOptions } from '@/utils/option.js'
 import Utils from '@/utils/utils.js'
@@ -14,19 +15,18 @@
 
 const { TextArea } = Input
 const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
-const FieldsTable = asyncComponent(() => import('./fieldtable'))
-const DataTable = asyncComponent(() => import('./datatable'))
+const FieldsTable = asyncComponent(() => import('@/templates/zshare/editTable'))
 const MkEditIcon = asyncComponent(() => import('@/components/mkIcon'))
 
 const modalTypeOptions = {
   text: ['initval', 'readonly', 'required', 'hidden', 'readin', 'fieldlength', 'regular', 'interception', 'span', 'labelwidth', 'encryption', 'tooltip', 'extra', 'enter', 'cursor', 'scan', 'splitline', 'placeholder', 'place', 'marginTop', 'marginBottom', 'lenControl', 'inputType', 'constant'],
   number: ['initval', 'readonly', 'hidden', 'decimal', 'min', 'max', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'enter', 'cursor', 'splitline', 'place', 'marginTop', 'marginBottom'],
-  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
+  select: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
   checkbox: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
-  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'setAll', 'emptyText', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
+  radio: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'splitline', 'arrange', 'marginTop', 'marginBottom'],
   checkcard: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'span', 'labelwidth', 'display', 'tooltip', 'extra', 'place', 'width', 'multiple', 'splitline', 'marginTop', 'marginBottom'],
   multiselect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'fieldlength', 'span', 'labelwidth', 'tooltip', 'extra', 'marginTop', 'marginBottom', 'dropdown'],
-  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'setAll', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'emptyText', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
+  link: ['initval', 'readonly', 'required', 'hidden', 'readin', 'resourceType', 'declare', 'linkField', 'linkSubField', 'span', 'place', 'labelwidth', 'tooltip', 'extra', 'enter', 'splitline', 'dropdown', 'marginTop', 'marginBottom', 'pickerMode'],
   fileupload: ['readonly', 'required', 'hidden', 'readin', 'fieldlength', 'maxfile', 'fileType', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'compress', 'miniSet', 'splitline', 'marginTop', 'marginBottom', 'maxSize'],
   switch: ['initval', 'openVal', 'closeVal', 'openText', 'closeText', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'linkSubField', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom'],
   check: ['initval', 'openVal', 'closeVal', 'readonly', 'hidden', 'readin', 'span', 'labelwidth', 'tooltip', 'extra', 'splitline', 'marginTop', 'marginBottom', 'checkTip'],
@@ -43,6 +43,7 @@
   brafteditor: ['required', 'hidelabel', 'hidden', 'readin', 'fieldlength', 'readonly', 'span', 'labelwidth', 'tooltip', 'extra', 'encryption', 'marginTop', 'marginBottom'],
   funcvar: ['span', 'labelwidth', 'splitline', 'marginTop', 'marginBottom'],
   linkMain: ['readonly', 'required', 'hidden','declare', 'span', 'labelwidth', 'tooltip', 'interception', 'extra', 'place', 'marginTop', 'marginBottom'],
+  popSelect: ['initval', 'readonly', 'required', 'hidden', 'readin', 'linkSubField', 'span', 'labelwidth', 'tooltip', 'extra', 'place', 'enter', 'dataSource', 'columns', 'primaryKey', 'order', 'controlField', 'laypage', 'onload', 'searchKey', 'showField', 'popWidth'],
   vercode: ['label', 'field', 'type', 'blacklist', 'supField', 'readonly', 'required', 'hidden', 'span', 'labelwidth', 'tooltip', 'marginTop', 'marginBottom', 'placeholder', 'enter', 'smsId', 'phoneField', 'sendType']
 }
 
@@ -429,41 +430,45 @@
         this.record.readonly = 'false'
       }
 
-      if (this.record.options.length > 0) {
-        if (value === 'checkcard') {
+      if (value === 'checkcard') {
+        if (this.record.options.length > 0) {
           this.record.options = this.record.options.map(cell => {
             cell.$value = cell.Value || ''
             delete cell.Value
             return cell
           })
+        }
   
-          if (this.record.options[0].Text) {
-            let key = Utils.getuuid()
-    
-            this.record.fields = [{
-              $index: 1,
-              align: 'left',
-              color: 'rgba(0, 0, 0, 0.85)',
-              field: 'Text',
-              fontSize: 14,
-              key: key,
-              uuid: key
-            }]
-          }
-        } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(value)) {
+        if (this.record.options[0] && this.record.options[0].Text) {
+          let key = Utils.getuuid()
+  
+          this.record.fields = [{
+            $index: 1,
+            align: 'left',
+            color: 'rgba(0, 0, 0, 0.85)',
+            field: 'Text',
+            fontSize: 14,
+            key: key,
+            uuid: key
+          }]
+        } else {
+          this.record.fields = []
+        }
+      } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(value)) {
+        if (this.record.options.length > 0) {
           if (!this.record.options[0].Text && this.record.fields.length > 0) {
             let field = this.record.fields[0].field
     
             this.record.options = this.record.options.map(cell => {
               cell.Value = cell.Value || cell.$value || ''
               cell.Text = cell[field] || ''
-    
+              delete cell.$value
               return cell
             })
           } else {
             this.record.options = this.record.options.map(cell => {
               cell.Value = cell.Value || cell.$value || ''
-    
+              delete cell.$value
               return cell
             })
           }
@@ -514,12 +519,8 @@
     this.record[key] = value
   }
 
-  changeField = (data) => {
-    this.record.fields = data || []
-  }
-
-  changeOptions = (data) => {
-    this.record.options = data || []
+  changeOptions = (data, key) => {
+    this.record[key] = data || []
   }
 
   changeVal = (val, type) => {
@@ -636,18 +637,15 @@
             message: '涓嶅彲浣跨敤鑻辨枃鐘舵�佺殑鍗曞紩鍙凤紒'
           }
         ]
-        if (item.key === 'field') {
+        if (item.rules) {
+          rules.push(...item.rules)
+        } else if (item.key === 'field') {
           rules.push({
             pattern: formRule.field.pattern,
             message: formRule.field.message
           }, {
             max: formRule.field.max,
             message: formRule.field.maxMessage
-          })
-        } else if (item.key === 'regularExtra') {
-          rules.push({
-            pattern: /^[~!@#$%^&*()_+:;{}<>,.-]*$/,
-            message: '鎵╁睍绗﹀寘鎷瑍!@#$%^&*()_+:;{}<>,.-'
           })
         } else if (item.max) {
           rules.push({
@@ -673,7 +671,7 @@
             <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
           </AutoComplete>
         } else {
-          content = <Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />
+          content = <Input placeholder={item.placeholder || ''} autoComplete="off" onPressEnter={this.handleSubmit} />
         }
       } else if (item.type === 'number') {
         rules = [
@@ -690,6 +688,12 @@
         rules = [
           { required: item.required, message: '璇烽�夋嫨' + item.label + '!' }
         ]
+
+        let options = item.options
+        if (typeof(item.options) === 'string') {
+          options = this.record[item.options] || []
+        }
+
         content = <Select
           showSearch
           allowClear={item.allowClear === true}
@@ -697,7 +701,7 @@
           onChange={(value) => {this.optionChange(item.key, value)}}
           getPopupContainer={() => document.getElementById('modal-fields-form-box')}
         >
-          {item.options.map((option, i) =>
+          {options.map((option, i) =>
             <Select.Option key={`${i}`} value={option.value || option.field || ''}>
               {option.text || option.label}
             </Select.Option>
@@ -778,7 +782,21 @@
               linkSubFields = []
             }
           }
-          content = <EditTable type={type} module="form" transfield={transfield} linkSubFields={linkSubFields} onChange={this.changeOptions}/>
+
+          let columns = []
+          if (type === 'link') {
+            columns.push({ title: 'ParentID', key: 'ParentID', strict: true })
+          }
+          columns.push({ title: 'Value', key: 'Value', strict: true })
+          columns.push({ title: 'Text', key: 'Text' })
+
+          linkSubFields.forEach(field => {
+            if (field === 'Value' || field === 'Text') return
+
+            columns.push({ title: transfield[field] || field, key: field })
+          })
+
+          content = <EditTable columns={columns} module="form" onChange={(data) => this.changeOptions(data, item.key)}/>
         } else {
           if (this.record.multiple === 'true') {
             linkSubFields = []
@@ -786,7 +804,34 @@
           if (this.record.linkField) {
             type = 'link'
           }
-          content = <DataTable type={type} display={this.record.display} linkSubFields={linkSubFields} transfield={transfield} fields={this.record.fields || []} onChange={this.changeOptions}/>
+
+          let columns = []
+          let fields = this.record.fields || []
+          let keys = ['ParentID', 'pid']
+
+          if (type === 'link') {
+            columns.push({ title: 'ParentID', key: 'ParentID', strict: true })
+          }
+          columns.push({ title: 'Value', key: '$value', strict: true })
+
+          if (this.record.display === 'picture') {
+            columns.push({ title: 'url', key: '$url', type: 'file' })
+          } else if (this.record.display === 'color') {
+            columns.push({ title: 'Color', key: '$color' })
+          }
+
+          fields.forEach(item => {
+            keys.push(item.field)
+            columns.push({ title: item.field, key: item.field })
+          })
+
+          linkSubFields.forEach(m => {
+            if (keys.includes(m)) return
+
+            columns.push({ title: transfield[m] || m, key: m })
+          })
+
+          content = <EditTable columns={columns} onChange={(data) => this.changeOptions(data, item.key)}/>
         }
       } else if (item.type === 'fields') {
         span = 24
@@ -795,7 +840,7 @@
           { required: item.required, message: '璇锋坊鍔�' + item.label + '!' }
         ]
 
-        content = <FieldsTable onChange={this.changeField}/>
+        content = <FieldsTable indexShow={false} actions={['edit', 'move', 'del', 'add']} columns={item.columns} data={this.record[item.key] || []} onChange={(data) => this.changeOptions(data, item.key)}/>
       } else if (item.type === 'color') {
         className = 'color-form-item'
         rules = [
@@ -836,7 +881,7 @@
 
     let isNumber = true
     options.forEach(item => {
-      if (!/^([0-9]|[1-9]\d{0,2})$/.test(item.Value)) {
+      if (!item.Value || isNaN(item.Value)) {
         isNumber = false
       }
     })
@@ -877,12 +922,36 @@
     }
   }
 
-  handleConfirm = () => {
+  handleConfirm = (fields) => {
+    const { card } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
-          values.uuid = this.props.card.uuid
+          values.uuid = card.uuid
+
+          if (card.style) {
+            values.style = card.style
+          }
+
+          let fieldrepet = false // 瀛楁閲嶅
+
+          fields.forEach(item => {
+            if (item.uuid === card.uuid || !values.field || !item.field) return
+            if (item.field.toLowerCase() === values.field.toLowerCase()) {
+              fieldrepet = true
+            }
+          })
+
+          if (fieldrepet) {
+            notification.warning({
+              top: 92,
+              message: '瀛楁宸插瓨鍦紒',
+              duration: 10
+            })
+            return
+          }
+
           // 涓嬫媺鑿滃崟鎴栬仈鍔ㄨ彍鍗�
           if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(values.type)) {
             if (values.resourceType === '0') {
@@ -1020,7 +1089,93 @@
             return
           }
 
-          resolve(values)
+          window.GLOB.formId = card.uuid
+
+          if (['select', 'multiselect', 'link', 'checkbox', 'radio', 'checkcard'].includes(values.type) && values.resourceType === '1' && values.dataSource) {
+            let _option = Utils.getSelectQueryOptions(values)
+
+            let sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+            ${_option.sql}`
+    
+            // LoginUID|SessionUid|UserID|Appkey 宸叉浛鎹�
+            sql = sql.replace(/@\$|\$@/ig, '').replace(/@(BID|ID|time_id)@/ig, `'1949-10-01 15:00:00'`)
+    
+            let rduri = ''
+            if (window.GLOB.mainSystemApi && values.database === 'sso') {
+              rduri = window.GLOB.mainSystemApi
+            }
+            
+            resolve({values, loading: true, promise: () => new Promise((resolve, reject) => {
+              Api.sDebug(sql, rduri).then(result => {
+                if (result.status || result.ErrCode === '-2') {
+                  resolve()
+                } else {
+                  Modal.error({
+                    title: result.message
+                  })
+                  reject()
+                }
+              })
+            })})
+          } else if (values.type === 'popSelect') {
+            let arrfield = values.columns.map(f => f.field)
+  
+            if (values.linkSubField && values.linkSubField.length > 0) {
+              values.linkSubField.forEach(n => {
+                if (!arrfield.includes(n)) {
+                  arrfield.push(n)
+                }
+              })
+            }
+  
+            let _datasource = values.dataSource
+            let sql = ''
+  
+            if (/\s/.test(_datasource)) { // 鎷兼帴鍒悕
+              _datasource = '(' + _datasource + ') tb'
+            }
+  
+            arrfield = arrfield.join(',')
+  
+            let _search = ''
+
+            if (values.searchKey) {
+              let fields = values.searchKey.split(',').map(field => field + ' like \'%mk%\'')
+              _search = 'where ' + fields.join(' OR ')
+            }
+  
+            if (values.laypage === 'true') {
+              sql = `/*system_query*/select top 10 ${arrfield} from (select ${arrfield} ,ROW_NUMBER() over(order by ${values.order}) as rows from ${_datasource} ${_search}) tmptable where rows > 0 order by tmptable.rows `
+            } else if (values.order) {
+              sql = `/*system_query*/select ${arrfield} from (select ${arrfield} ,ROW_NUMBER() over(order by ${values.order}) as rows from ${_datasource} ${_search}) tmptable order by tmptable.rows `
+            } else {
+              sql = `/*system_query*/select ${arrfield} from ${_datasource} ${_search}  `
+            }
+  
+            sql = `declare @mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20)
+              ${sql}`
+  
+            sql = sql.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            sql = sql.replace(/@LoginUID@/ig, `'${sessionStorage.getItem('LoginUID') || ''}'`)
+            sql = sql.replace(/@SessionUid@/ig, `'${localStorage.getItem('SessionUid') || ''}'`)
+            sql = sql.replace(/@UserID@/ig, `'${sessionStorage.getItem('UserID') || ''}'`)
+            sql = sql.replace(/@Appkey@/ig, `'${window.GLOB.appkey || ''}'`)
+  
+            resolve({values, loading: true, promise: () => new Promise((resolve, reject) => {
+              Api.sDebug(sql).then(result => {
+                if (result.status || result.ErrCode === '-2') {
+                  resolve()
+                } else {
+                  Modal.error({
+                    title: result.message
+                  })
+                  reject()
+                }
+              })
+            })})
+          } else {
+            resolve({values})
+          }
         } else {
           reject(err)
         }
diff --git a/src/templates/zshare/modalform/modaleditable/index.jsx b/src/templates/zshare/modalform/modaleditable/index.jsx
index b8ca161..0427a95 100644
--- a/src/templates/zshare/modalform/modaleditable/index.jsx
+++ b/src/templates/zshare/modalform/modaleditable/index.jsx
@@ -1,106 +1,138 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
-import { Table, Input, Popconfirm, Form, message } from 'antd'
-import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
+import { DndProvider, DragSource, DropTarget } from 'react-dnd'
+import { Table, Input, Popconfirm, message } from 'antd'
+import { DeleteOutlined, PlusOutlined, SwapOutlined, DragOutlined } from '@ant-design/icons'
 
 import Utils from '@/utils/utils.js'
+import asyncComponent from '@/utils/asyncComponent'
 import './index.scss'
 
-const EditableContext = React.createContext()
+const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
 
-const EditableRow = ({ form, index, ...props }) => (
-  <EditableContext.Provider value={form}>
-    <tr {...props} />
-  </EditableContext.Provider>
+class MoveTd extends React.Component {
+  render() {
+    const { connectDragSource, connectDropTarget } = this.props
+
+    return connectDragSource(
+      connectDropTarget(<td className="mk-move-col"><DragOutlined /></td>),
+    )
+  }
+}
+
+const rowSource = {
+  beginDrag(props) {
+    return {
+      index: props.index,
+    }
+  }
+}
+
+const rowTarget = {
+  drop(props, monitor) {
+    const dragIndex = monitor.getItem().index
+    const hoverIndex = props.index
+
+    if (dragIndex === hoverIndex) {
+      return
+    }
+
+    props.moveRow(dragIndex, hoverIndex)
+
+    monitor.getItem().index = hoverIndex
+  },
+}
+
+const DragableTd = DropTarget('td', rowTarget, connect => ({
+  connectDropTarget: connect.dropTarget(),
+}))(
+  DragSource('td', rowSource, (connect, monitor) => ({
+    connectDragSource: connect.dragSource(),
+    // isDragging: monitor.isDragging()
+  }))(MoveTd),
 )
-
-const EditableFormRow = Form.create()(EditableRow)
 
 class EditableCell extends Component {
   state = {
-    editing: false
+    editing: false,
+    value: ''
   }
 
-  toggleEdit = () => {
-    const editing = !this.state.editing
-    this.setState({ editing }, () => {
-      if (editing && this.input && this.input.select) {
+  trigger = () => {
+    const { dataIndex, record } = this.props
+
+    this.setState({ editing: true, value: record[dataIndex] }, () => {
+      if (this.input && this.input.select) {
         this.input.select()
-      } else if (editing && this.input && this.input.focus) {
+      } else if (this.input && this.input.focus) {
         this.input.focus()
       }
     })
   }
 
-  save = e => {
-    const { record, handleSave } = this.props
-    this.form.validateFields((error, values) => {
-      handleSave({ ...record, ...values })
-      if (error && error[e.currentTarget.id]) {
-        return
-      }
-      this.toggleEdit()
-    })
+  save = () => {
+    const { record, handleSave, dataIndex } = this.props
+    const { value } = this.state
+
+    handleSave({ ...record, [dataIndex]: value })
+
+    this.setState({ editing: false, value: '' })
   }
 
-  renderCell = form => {
-    this.form = form
-    const { children, dataIndex, record } = this.props
+  changeUrl = (val) => {
+    const { record, handleSave, dataIndex } = this.props
+
+    handleSave({ ...record, [dataIndex]: val })
+  }
+
+  renderCell = () => {
+    const { dataIndex, inputType, record } = this.props
     const { editing } = this.state
 
-    return editing ? (
-      <Form.Item style={{ margin: '0 -5px 0 -5px' }}>
-        {form.getFieldDecorator(dataIndex, {
-          rules: [
-            {
-              required: dataIndex === 'Text',
-              message: '涓嶅彲涓虹┖.',
-            }
-          ],
-          initialValue: record[dataIndex]
-        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
-      </Form.Item>
-    ) : (
-      <div
-        className="editable-cell-value-wrap"
-        onClick={this.toggleEdit}
-      >
-        {children}
-      </div>
-    )
+    if (inputType === 'file') {
+      return <SourceComponent initialValue={record[dataIndex]} type="" onChange={this.changeUrl} placement="right"/>
+    }
+
+    if (!editing) {
+      return (
+        <div
+          className="editable-cell-value-wrap"
+          onClick={this.trigger}
+        >
+          {record[dataIndex]}
+        </div>
+      )
+    } else {
+      return <Input ref={node => (this.input = node)} defaultValue={record[dataIndex]} autoComplete="off" onChange={(e) => this.setState({value: e.target.value})} onPressEnter={this.save} onBlur={this.save} />
+    }
   }
 
   render() {
-    const {
-      editable,
-      dataIndex,
-      title,
-      record,
-      index,
-      handleSave,
-      children,
-      ...restProps
-    } = this.props
+    const { editable, dataIndex, index } = this.props
+
+    if (dataIndex === '$move') {
+      return (<DragableTd key={index} {...this.props} />)
+    }
+
+    if (editable) {
+      return (
+        <td>{this.renderCell()}</td>
+      )
+    }
+
     return (
-      <td {...restProps}>
-        {editable ? (
-          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
-        ) : (
-          children
-        )}
-      </td>
+      <td {...this.props}/>
     )
   }
 }
 
 class EditTable extends Component {
   static propTpyes = {
-    type: PropTypes.string,         // 琛ㄥ崟绫诲瀷
-    module: PropTypes.string,       // 鍏冪礌绫诲瀷
-    linkSubFields: PropTypes.array, // 鍏宠仈瀛楁
-    transfield: PropTypes.object,   // 琛ㄥ崟瀛楁鍚嶇О
-    onChange: PropTypes.func        // 鏁版嵁鍙樺寲
+    type: PropTypes.any,
+    module: PropTypes.string,
+    columns: PropTypes.array,
+    onChange: PropTypes.func
   }
 
   state = {
@@ -110,38 +142,40 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { linkSubFields, type } = this.props
-    let data = this.props['data-__meta'].initialValue || []
-
-    const { columns } = this.getColumns(type, linkSubFields, data)
+    const { columns, value } = this.props
+    let data = value || []
 
     this.setState({
-      columns: columns,
-      dataSource: data,
+      columns: this.getColumns(),
+      dataSource: data.map(item => {
+        columns.forEach(n => {
+          if (item[n.key] !== undefined) return
+          item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
+        })
+        return item
+      }),
       count: data.length
     })
   }
 
-  handleUpDown = (record, direction) => {
+  moveRow = (dragId, hoverId) => {
     const { dataSource } = this.state
-    let index = 0
-
-    let _data = dataSource.filter((item, i) => {
-      if (item.key === record.key) {
-        index = i
+    let dragIndex = -1
+    let hoverIndex = -1
+    
+    dataSource.forEach((item, i) => {
+      if (item.key === dragId) {
+        dragIndex = i
+      } else if (item.key === hoverId) {
+        hoverIndex = i
       }
-
-      return item.key !== record.key
     })
-    if ((index === 0 && direction === 'up') || (index === dataSource.length - 1 && direction === 'down')) {
-      return
-    }
+    
+    if (dragIndex === -1 || hoverIndex === -1) return
 
-    if (direction === 'up') {
-      _data.splice(index - 1, 0, record)
-    } else {
-      _data.splice(index + 1, 0, record)
-    }
+    let _data = fromJS(dataSource).toJS()
+
+    _data.splice(hoverIndex, 0, ..._data.splice(dragIndex, 1))
 
     this.setState({
       dataSource: _data
@@ -150,13 +184,14 @@
     })
   }
 
-  handleHide = (record) => {
+  handleHide = (key) => {
     let _data = this.state.dataSource.map(item => {
-      if (item.key === record.key) {
+      if (item.key === key) {
         item.Hide = !item.Hide
       }
       return item
     })
+
     this.setState({
       dataSource: _data
     }, () => {
@@ -164,7 +199,7 @@
     })
   }
 
-  handleDelete = key => {
+  handleDelete = (key) => {
     const { dataSource } = this.state
     let _data = dataSource.filter(item => item.key !== key)
 
@@ -173,22 +208,26 @@
     })
   }
 
-  handleAdd = (e) => {
-    e.stopPropagation()
-    const { linkSubFields } = this.props
+  handleAdd = () => {
+    const { columns } = this.props
     const { count, dataSource } = this.state
-    const newData = {
-      key: Utils.getuuid(),
-      Value: `${count}`,
-      Text: `${count}`,
-      ParentID: ''
-    }
 
-    linkSubFields.forEach(m => {
-      newData[m] = newData[m] || ''
+    let item = { key: Utils.getuuid() }
+
+    columns.forEach(m => {
+      item[m.key] = ''
     })
 
-    let _data = [...dataSource, newData]
+    if (item.Value === '') {
+      item.Value = `${count + 1}`
+    }
+    if (item.$value === '') {
+      item.$value = `${count + 1}`
+    }
+
+    item.Text = `${count + 1}`
+
+    let _data = [...dataSource, item]
 
     this.setState({
       dataSource: _data,
@@ -199,18 +238,49 @@
   }
 
   handleSave = row => {
-    const { type } = this.props
+    const { columns, type } = this.props
     const newData = [...this.state.dataSource]
     const index = newData.findIndex(item => row.key === item.key)
     const item = newData[index]
 
-    if (type === 'link') {
-      if (newData.filter(m => row.key !== m.key && row.Value === m.Value && row.ParentID === m.ParentID).length > 0) {
-        message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
-      }
+    if (type === 'proc') {
+      // if (!row.origin || /^\s+$/.test(row.origin)) {
+      //   message.warning(columns[0].title + '涓虹┖鏃舵棤鏁堬紒')
+      // }
     } else {
-      if (newData.filter(m => row.key !== m.key && row.Value === m.Value).length > 0) {
-        message.warning('姝alue鍊煎凡瀛樺湪锛�')
+      let val = ''
+      let repeat = false
+      let _type = ''
+      columns.forEach(col => {
+        if (!col.strict) return
+  
+        if (col.key === 'ParentID') {
+          _type = 'mutil'
+        }
+  
+        val += row[col.key]
+      })
+  
+      newData.forEach(item => {
+        if (row.key === item.key) return
+  
+        let _val = ''
+        columns.forEach(col => {
+          if (!col.strict) return
+  
+          _val += item[col.key]
+        })
+  
+        if (val === _val) {
+          repeat = true
+        }
+      })
+      if (repeat) {
+        if (_type === 'mutil') {
+          message.warning('鐩稿悓ParentID涓嬶紝姝alue鍊煎凡瀛樺湪锛�')
+        } else {
+          message.warning('姝alue鍊煎凡瀛樺湪锛�')
+        }
       }
     }
 
@@ -223,112 +293,83 @@
     })
   }
 
-  getColumns = (type, linkSubFields, dataSource) => {
-    const { transfield } = this.props
+  getColumns = () => {
+    const { columns } = this.props
 
-    let _dataSource = fromJS(dataSource).toJS()
-    let fields = []
-    let subFields = linkSubFields.filter(m => m !== 'Value' && m !== 'Text')
-
-    if (subFields.length > 0) {
-      _dataSource = _dataSource.map(data => {
-        subFields.forEach(n => {
-          if (data[n] !== undefined) return
-          data[n] = data.Text || ''
-        })
-        return data
+    let fields = [{
+      title: ' ',
+      width: '60px',
+      dataIndex: '$move',
+      onCell: (record) => ({
+        index: record.key,
+        dataIndex: '$move',
+        moveRow: this.moveRow
       })
-
-      fields = subFields.map(field => {
-        return {
-          title: transfield[field] || field,
-          $title: transfield[field] || field,
-          dataIndex: field,
+    }]
+    columns.forEach(n => {
+      let col = {
+        title: n.title,
+        dataIndex: n.key,
+        onCell: record => ({
+          record,
           editable: true,
-        }
-      })
-    }
-
-    let columns = [
-      {
-        title: 'Value',
-        $title: 'Value',
-        dataIndex: 'Value',
-        editable: true
-      },
-      {
-        title: 'Text',
-        $title: 'Text',
-        dataIndex: 'Text',
-        editable: true
-      },
-      ...fields,
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        width: '20%',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <div style={{fontSize: '15px'}}>
-              <span className="operation-btn" onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><ArrowUpOutlined /></span>
-              <span className="operation-btn" onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><ArrowDownOutlined /></span>
-              <span className="operation-btn" title="鏄剧ず/闅愯棌" onClick={() => this.handleHide(record)} style={{color: 'rgb(142, 68, 173)'}}><SwapOutlined /></span>
-              <Popconfirm
-                title="纭畾鍒犻櫎鍚楋紵"
-                overlayClassName="popover-confirm"
-                onConfirm={() => this.handleDelete(record.key)
-              }>
-                <span style={{color: '#ff4d4f', cursor: 'pointer'}}><DeleteOutlined /></span>
-              </Popconfirm>
-            </div>
-          ) : null,
+          inputType: n.type || 'text',
+          dataIndex: n.key,
+          handleSave: this.handleSave
+        })
       }
-    ]
 
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        $title: 'ParentID',
-        dataIndex: 'ParentID',
-        editable: true
-      })
-    }
+      if (n.width) {
+        col.width = n.width
+      }
+      if (n.fixed) {
+        delete col.onCell
+      }
 
-    return {
-      columns: columns.map(col => {
-        if (col.dataIndex !== 'operation') {
-          col.title = <div>
-            {col.$title}
+      fields.push(col)
+    })
+
+    fields.push({
+      title: '鎿嶄綔',
+      align: 'center',
+      width: '110px',
+      dataIndex: 'operation',
+      render: (text, record) =>
+        (
+          <div style={{fontSize: '15px'}}>
+            <span className="operation-btn" title="鏄剧ず/闅愯棌" onClick={() => this.handleHide(record.key)} style={{color: 'rgb(142, 68, 173)'}}><SwapOutlined /></span>
+            <Popconfirm
+              title="纭畾鍒犻櫎鍚楋紵"
+              overlayClassName="popover-confirm"
+              onConfirm={() => this.handleDelete(record.key)
+            }>
+              <span style={{color: '#ff4d4f', cursor: 'pointer'}}><DeleteOutlined /></span>
+            </Popconfirm>
           </div>
-        }
-        return col
-      }),
-      dataSource: _dataSource
-    }
+        )
+    })
+
+    return fields
   }
 
-  handleEmpty = (e) => {
-    e.stopPropagation()
-    const { linkSubFields, module } = this.props
+  handleEmpty = () => {
+    const { columns, module } = this.props
     const { dataSource } = this.state
 
     if (dataSource.filter(item => item.Value === '').length > 0) {
       message.warning('Value涓虹┖宸插瓨鍦紒')
       return
     }
-    const newData = {
-      key: Utils.getuuid(),
-      Value: '',
-      Text: module === 'form' ? '绌�' : '鍏ㄩ儴',
-      ParentID: ''
-    }
 
-    linkSubFields.forEach(m => {
-      newData[m] = newData[m] || ''
+    let item = { key: Utils.getuuid() }
+
+    columns.forEach(m => {
+      item[m.key] = ''
     })
 
-    let _data = [newData, ...dataSource]
+    item.Text = module === 'form' ? '绌�' : '鍏ㄩ儴'
+
+    let _data = [item, ...dataSource]
 
     this.setState({
       dataSource: _data,
@@ -337,65 +378,57 @@
     })
   }
 
-  resetColumn = (type, linkSubFields) => {
-    const { columns, dataSource } = this.getColumns(type, linkSubFields, this.state.dataSource)
+  resetColumn = () => {
+    const { columns, value } = this.props
+    
+    let data = fromJS(value).toJS().map(item => {
+      columns.forEach(n => {
+        if (item[n.key] !== undefined) return
+        item[n.key] = ['ParentID', '$url', '$color', '$value'].includes(n.key) ? '' : item.Text || ''
+      })
+      return item
+    })
 
-    if (!is(fromJS(dataSource), fromJS(this.state.dataSource))) {
-      this.setState({
-        columns,
-        dataSource
-      }, () => {
-        this.props.onChange(dataSource)
-      })
-    } else {
-      this.setState({
-        columns
-      })
-    }
+    this.setState({
+      columns: this.getColumns(),
+      dataSource: data,
+      count: data.length
+    }, () => {
+      this.props.onChange(data)
+    })
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
-    if (!is(fromJS(this.props.linkSubFields), fromJS(nextProps.linkSubFields)) || this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type, nextProps.linkSubFields)
+    if (!is(fromJS(this.props.columns), fromJS(nextProps.columns))) {
+      this.setState({}, () => {
+        this.resetColumn()
+      })
     }
   }
 
   render() {
     const { module } = this.props
-    const { dataSource } = this.state
+    const { dataSource, columns } = this.state
     const components = {
       body: {
-        row: EditableFormRow,
         cell: EditableCell
       }
     }
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          editable: col.editable,
-          dataIndex: col.dataIndex,
-          title: col.title,
-          handleSave: this.handleSave
-        })
-      }
-    })
+
     return (
       <div className="common-modal-edit-table">
-        <span className="add-row add-row-empty" onClick={this.handleEmpty}>{module === 'form' ? '绌�' : '鍏ㄩ儴'}</span>
+        {module ? <span className="add-row add-row-empty" onClick={this.handleEmpty}>{module === 'form' ? '绌�' : '鍏ㄩ儴'}</span> : null}
         <PlusOutlined className="add-row" onClick={this.handleAdd} />
-        <Table
-          components={components}
-          rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
-          bordered
-          dataSource={dataSource}
-          columns={columns}
-          pagination={false}
-        />
+        <DndProvider>
+          <Table
+            components={components}
+            rowClassName={(record) => record.Hide ? 'editable-row hide' : 'editable-row'}
+            bordered
+            dataSource={dataSource}
+            columns={columns}
+            pagination={false}
+          />
+        </DndProvider>
       </div>
     )
   }
diff --git a/src/templates/zshare/modalform/modaleditable/index.scss b/src/templates/zshare/modalform/modaleditable/index.scss
index 7c097fd..3c93c9a 100644
--- a/src/templates/zshare/modalform/modaleditable/index.scss
+++ b/src/templates/zshare/modalform/modaleditable/index.scss
@@ -15,6 +15,15 @@
     color: #1890ff;
     cursor: pointer;
   }
+  .mk-move-col {
+    text-align: center;
+    font-size: 16px;
+    cursor: move;
+    color: #c8c8c8;
+  }
+  .mk-source-wrap {
+    min-width: 150px;
+  }
   .ant-table-thead > tr > th {
     padding: 10px 16px;
     position: relative;
@@ -23,7 +32,6 @@
       position: absolute;
       right: 12px;
       font-size: 14px;
-      // top: 12px;
       color: #b8b8b8;
     }
   }
@@ -52,7 +60,7 @@
     }
   }
   .operation-btn {
-    margin-right: 10px;
+    margin-right: 15px;
     cursor: pointer;
   }
   .editable-row.hide {
diff --git a/src/views/systemproc/proc/index.jsx b/src/views/systemproc/proc/index.jsx
index 62ce63a..577e462 100644
--- a/src/views/systemproc/proc/index.jsx
+++ b/src/views/systemproc/proc/index.jsx
@@ -6,6 +6,7 @@
 import Utils from '@/utils/utils.js'
 import Api from '@/api'
 import CodeMirror from '@/templates/zshare/codemirror'
+import Transfer from '../transfer'
 import './index.scss'
 
 const { confirm } = Modal
@@ -379,6 +380,7 @@
               {!inputing ? <Search placeholder="璇疯緭鍏ュ瓨鍌ㄨ繃绋嬪悕绉�" defaultValue={procName} disabled={loading} enterButton="纭畾" onSearch={this.search}/> : null}
             </div>
             <div className="action-wrap">
+              {!procName || loading || !content ? null : <Transfer procName={procName} content={content} />}
               <Button key="save" className="mk-btn mk-green" disabled={loading} onClick={() => this.save()}>淇濆瓨</Button>
               <Button key="prev" className="mk-btn mk-primary" disabled={!procName || loading} onClick={this.prev}>涓婁竴鐗堟湰</Button>
               <Button key="next" className="mk-btn mk-primary" disabled={!procName || loading} onClick={this.next}>涓嬩竴鐗堟湰</Button>
diff --git a/src/views/systemproc/transfer/index.jsx b/src/views/systemproc/transfer/index.jsx
new file mode 100644
index 0000000..1e44418
--- /dev/null
+++ b/src/views/systemproc/transfer/index.jsx
@@ -0,0 +1,289 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { DndProvider } from 'react-dnd'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { Button, Modal, notification, Form, Select } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import Api from '@/api'
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const EditTable = asyncComponent(() => import('@/templates/zshare/modalform/modaleditable'))
+
+class TransferWrap extends Component {
+  static propTpyes = {
+    MenuID: PropTypes.string
+  }
+
+  state = {
+    visible: false,
+    loading: false,
+    VersionName: '',
+    translist: [],
+    options: []
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  verifySubmit = () => {
+    const { content, procName } = this.props
+    const { VersionName, options } = this.state
+    let value = content.replace(/^(\s*)|(\s*)$/ig, '')
+
+    if (!VersionName) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨浼犺緭鍙�',
+        duration: 5
+      })
+      return
+    } else if (!value) {
+      notification.warning({
+        top: 92,
+        message: '瀛樺偍杩囩▼涓嶅彲涓虹┖',
+        duration: 5
+      })
+      return
+    }
+
+    let regs = []
+    options.forEach(item => {
+      if (item.origin && !/^\s+$/.test(item.origin) && item.origin !== item.value) {
+        regs.push({reg: new RegExp(item.origin, 'g'), value: item.value})
+      }
+    })
+
+    regs.forEach(item => {
+      value = value.replace(item.reg, item.value)
+    })
+
+    let chars = [
+      {key: 'drop', reg: /(^|\s)drop\s/ig},
+      {key: 'alter', reg: /(^|\s)alter\s/ig},
+      {key: 'object', reg: /(^|\s)object(\s|\()/ig},
+      {key: 'kill', reg: /(^|\s)kill\s/ig},
+      {key: '--', reg: /--/ig},
+      {key: ',,', reg: /,,/ig}
+    ]
+
+    let error = ''
+
+    if (!/create(\s+)proc/ig.test(value)) {
+      error = '鑴氭湰涓繀椤讳娇鐢╟reate proc'
+    }
+  
+    chars.forEach(char => {
+      if (!error && char.reg.test(value)) {
+        error = '涓嶅彲浣跨敤' + char.key
+      }
+    })
+
+    if (error) {
+      notification.warning({
+        top: 92,
+        message: error,
+        duration: 5
+      })
+      return
+    }
+
+    let dropfunc = `IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('${procName}') AND type in (N'P', N'PC'))  mdrpk PROCEDURE ${procName}`
+
+    let dropParam = {
+      func: 's_sVersionDetail_Add',
+      BID: VersionName,
+      VType: 'VSQL',
+      VSQL: window.btoa(window.encodeURIComponent(dropfunc))
+    }
+
+    let addParam = {
+      func: 's_sVersionDetail_Add',
+      BID: VersionName,
+      VType: 'VSQL',
+      VSQL: window.btoa(window.encodeURIComponent(value))
+    }
+
+    this.setState({
+      loading: true
+    })
+
+    Api.genericInterface(dropParam).then(result => {
+      if (!result.status) {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+        this.setState({
+          loading: false
+        })
+        return
+      }
+
+      delete result.status
+      delete result.message
+      delete result.ErrCode
+      delete result.ErrMesg
+      result.func = 's_sVersionDetail_CloudAdd'
+
+      Api.genericInterface(addParam).then(res => {
+        if (!res.status) {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 5
+          })
+          this.setState({
+            loading: false
+          })
+          return
+        }
+  
+        delete res.status
+        delete res.message
+        delete res.ErrCode
+        delete res.ErrMesg
+        res.func = 's_sVersionDetail_CloudAdd'
+        
+        Api.getCloudConfig(result).then(re => {
+          if (!re.status) {
+            notification.warning({
+              top: 92,
+              message: re.message,
+              duration: 5
+            })
+            this.setState({
+              loading: false
+            })
+            return
+          }
+
+          Api.getCloudConfig(res).then(r => {
+            if (!r.status) {
+              notification.warning({
+                top: 92,
+                message: r.message,
+                duration: 5
+              })
+              this.setState({
+                loading: false
+              })
+              return
+            } else {
+              notification.success({
+                top: 92,
+                message: '娣诲姞鎴愬姛锛�',
+                duration: 3
+              })
+              this.setState({
+                loading: false,
+                visible: false
+              })
+            }
+          })
+        })
+      })
+    })
+  }
+
+  getTransList = () => {
+    const { content } = this.props
+    let value = content.replace(/^(\s*)|(\s*)$/ig, '')
+
+    if (!value) {
+      notification.warning({
+        top: 92,
+        message: '瀛樺偍杩囩▼涓嶅彲涓虹┖',
+        duration: 5
+      })
+      return
+    }
+
+    let param = {
+      func: 's_get_sVersion',
+      dataM: 'Y',
+      PageSize: 9999,
+      PageIndex: 1,
+      OrderCol: 'ID desc'
+    }
+
+    let options = []
+
+    let list = value.match(/\s+[a-z0-9_]+\.(dbo)?\./ig)
+    list && list.forEach(str => {
+      str = str.replace(/^\s/, '')
+      options.push({
+        key: Utils.getuuid(),
+        origin: str,
+        value: str
+      })
+    })
+
+    this.setState({
+      options: options,
+      VersionName: '',
+      visible: true,
+      loading: false
+    })
+
+    Api.getCloudConfig(param).then(result => {
+      if (result.status) {
+        this.setState({
+          translist: result.data
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: result.message,
+          duration: 5
+        })
+      }
+    })
+  }
+
+  changeOptions = (value) => {
+    this.setState({options: value})
+  }
+
+  render () {
+    const { visible, loading, translist, options } = this.state
+    const columns = [{ title: '鍘熶俊鎭�', key: 'origin', width: '50%', fixed: true }, { title: '鏇挎崲涓�', width: '50%', key: 'value' }]
+
+    return (
+      <>
+        <Button icon="pull-request" className="mk-border-green" onClick={this.getTransList}>浼犺緭鍙�</Button>
+        <Modal
+          title="鍔犲叆浼犺緭鍙�"
+          wrapClassName="proc-transfer"
+          visible={visible}
+          width={900}
+          maskClosable={false}
+          okText="纭畾"
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          confirmLoading={loading}
+          destroyOnClose
+        >
+          <Form.Item label="浼犺緭鍙�">
+            <Select onChange={(val) => this.setState({VersionName: val})}>
+              {translist.map(option =>
+                <Select.Option key={option.VersionName} value={option.VersionName}>{`${option.ProgramName}(${option.VersionName})`}</Select.Option>
+              )}
+            </Select>
+          </Form.Item>
+          {options.length > 0 ? <DndProvider backend={HTML5Backend}>
+            <Form.Item label="鏇挎崲椤�">
+              <EditTable type="proc" columns={columns} value={options} onChange={this.changeOptions}/>
+            </Form.Item>
+          </DndProvider> : null}
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default TransferWrap
\ No newline at end of file
diff --git a/src/views/systemproc/transfer/index.scss b/src/views/systemproc/transfer/index.scss
new file mode 100644
index 0000000..fbcf2ce
--- /dev/null
+++ b/src/views/systemproc/transfer/index.scss
@@ -0,0 +1,18 @@
+.proc-transfer {
+  .ant-form-item {
+    display: flex;
+    .ant-form-item-control-wrapper {
+      flex: 10;
+
+      .ant-select {
+        width: 300px;
+      }
+    }
+  }
+  .operation-btn {
+    display: none;
+  }
+  .add-row {
+    display: none;
+  }
+}
\ No newline at end of file
diff --git a/src/views/tabledesign/source.jsx b/src/views/tabledesign/source.jsx
index 5e43351..058c775 100644
--- a/src/views/tabledesign/source.jsx
+++ b/src/views/tabledesign/source.jsx
@@ -186,6 +186,18 @@
     },
     {
       type: 'col',
+      label: '鑷畾涔夊垪',
+      subType: 'custom',
+      $init: true
+    },
+    {
+      type: 'col',
+      label: '鍏紡',
+      subType: 'formula',
+      $init: true
+    },
+    {
+      type: 'col',
       label: '鍥剧墖',
       subType: 'picture',
       $init: true
@@ -210,20 +222,8 @@
     },
     {
       type: 'col',
-      label: '鑷畾涔夊垪',
-      subType: 'custom',
-      $init: true
-    },
-    {
-      type: 'col',
       label: '鍚堝苟鍒�',
       subType: 'colspan',
-      $init: true
-    },
-    {
-      type: 'col',
-      label: '鍏紡',
-      subType: 'formula',
       $init: true
     },
     {

--
Gitblit v1.8.0