From 6781ba45775af16872ac68f7e459b1072b16c4cc Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 18 十月 2023 17:33:47 +0800
Subject: [PATCH] Merge branch 'master' into positec

---
 src/views/systemproc/proc/index.jsx                                      |    2 
 src/templates/zshare/modalform/index.jsx                                 |  254 +++
 src/menu/components/form/formaction/index.scss                           |    3 
 src/utils/utils-datamanage.js                                            |   21 
 src/templates/zshare/editTable/index.jsx                                 |   75 +
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx     |   70 +
 src/menu/components/share/markcomponent/index.jsx                        |   45 
 src/templates/modalconfig/settingform/index.scss                         |    4 
 src/utils/utils-custom.js                                                |   88 
 src/menu/datasource/index.jsx                                            |   21 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx    |   11 
 src/views/tabledesign/source.jsx                                         |   24 
 src/menu/components/share/sourcecomponent/inputform/index.scss           |    4 
 src/menu/components/table/base-table/index.scss                          |    3 
 src/templates/modalconfig/index.jsx                                      |   67 
 src/menu/components/form/formaction/index.jsx                            |   15 
 src/mob/modalconfig/index.jsx                                            |   67 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                    |   21 
 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/datasource/verifycard/index.jsx                                 |   57 
 src/assets/css/main.scss                                                 |   19 
 src/menu/components/table/edit-table/columns/editColumn/formconfig.jsx   |   12 
 src/menu/components/form/formaction/formconfig.jsx                       |    2 
 src/menu/components/table/edit-table/index.scss                          |    5 
 src/tabviews/custom/components/card/cardcellList/index.jsx               |   40 
 src/menu/components/card/cardcellcomponent/index.jsx                     |    5 
 src/menu/components/form/tab-form/index.jsx                              |   64 
 src/tabviews/custom/components/table/edit-table/normalTable/index.jsx    |   68 
 src/tabviews/zshare/mutilform/mkPopSelect/index.jsx                      |  372 +++++
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss       |    8 
 src/tabviews/zshare/mutilform/index.jsx                                  |  201 +-
 src/tabviews/custom/components/chart/antv-X6/index.jsx                   |  162 ++
 src/tabviews/custom/index.jsx                                            |    9 
 src/menu/components/table/base-table/columns/index.jsx                   |    5 
 src/menu/debug/index.jsx                                                 |   13 
 src/menu/components/table/normal-table/index.jsx                         |   16 
 src/menu/components/table/normal-table/columns/index.jsx                 |   36 
 src/templates/zshare/modalform/modaleditable/index.jsx                   |  519 ++++---
 src/templates/sharecomponent/searchcomponent/searchform/index.jsx        |   66 
 src/tabviews/zshare/actionList/index.scss                                |    8 
 src/menu/components/table/normal-table/columns/editColumn/formconfig.jsx |   12 
 src/menu/components/share/sourcecomponent/inputform/index.jsx            |    2 
 src/tabviews/custom/components/module/account/index.jsx                  |    5 
 src/menu/components/form/formaction/actionform/index.jsx                 |    2 
 src/menu/components/card/prop-card/index.scss                            |    1 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx   |   12 
 src/menu/components/form/simple-form/options.jsx                         |    4 
 src/tabviews/zshare/actionList/exceloutbutton/index.jsx                  |    2 
 src/menu/components/form/simple-form/index.jsx                           |   72 
 src/menu/components/table/normal-table/index.scss                        |    3 
 src/tabviews/custom/components/share/normalTable/index.jsx               |   34 
 src/tabviews/zshare/topSearch/index.scss                                 |    2 
 src/tabviews/custom/components/form/simple-form/index.jsx                |   13 
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx   |    2 
 src/menu/sysinterface/index.jsx                                          |    6 
 src/views/systemproc/transfer/index.jsx                                  |  289 ++++
 src/utils/utils.js                                                       |  157 +
 src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx        |    2 
 src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx    |    2 
 src/menu/components/table/base-table/columns/index.scss                  |   19 
 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                                      |  350 ++++
 src/templates/zshare/verifycard/index.jsx                                |   15 
 src/menu/components/share/sourcecomponent/index.jsx                      |    2 
 src/menu/components/share/actioncomponent/index.jsx                      |   10 
 src/menu/modulecell/index.jsx                                            |    4 
 src/tabviews/zshare/actionList/printbutton/index.jsx                     |   21 
 /dev/null                                                                |   14 
 src/menu/modalconfig/index.scss                                          |   15 
 src/menu/modalconfig/index.jsx                                           |   71 
 src/templates/zshare/verifycard/baseform/index.jsx                       |   29 
 src/views/systemproc/transfer/index.scss                                 |   18 
 src/templates/zshare/modalform/modaleditable/index.scss                  |   12 
 78 files changed, 2,992 insertions(+), 948 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/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 1100466..3495c10 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -451,10 +451,7 @@
           } else if (res.class !== cell.class || res.show !== cell.show || !res.style) {
             let cl = res.class.replace('border-', '')
             let style = {}
-            if (res.show === 'link' || res.show === 'icon') {
-              style.color = color[cl]
-              style.backgroundColor = 'transparent'
-            } else if (res.class === 'default') {
+            if (res.class === 'default') {
               style.color = 'rgba(0, 0, 0, 0.65)'
               style.backgroundColor = '#fff'
               style.borderColor = '#d9d9d9'
diff --git a/src/menu/components/card/prop-card/index.scss b/src/menu/components/card/prop-card/index.scss
index 6f1ec06..5e0c1e5 100644
--- a/src/menu/components/card/prop-card/index.scss
+++ b/src/menu/components/card/prop-card/index.scss
@@ -82,6 +82,7 @@
     color: orange;
     float: right;
     margin: 5px;
+    clear: left;
   }
 }
 .menu-prop-card-edit-box::after {
diff --git a/src/menu/components/form/formaction/actionform/index.jsx b/src/menu/components/form/formaction/actionform/index.jsx
index b21638c..b65157b 100644
--- a/src/menu/components/form/formaction/actionform/index.jsx
+++ b/src/menu/components/form/formaction/actionform/index.jsx
@@ -54,7 +54,7 @@
       shows = ['typeName', 'label', 'actionType']
     } else if (this.record.type === 'next') {
       shows = ['typeName', 'label', 'actionType']
-    } else if (this.record.type === 'close') {
+    } else if (this.record.type === 'close' || this.record.type === 'reset') {
       shows = ['typeName', 'label']
     } else {
       shows = ['typeName', 'label', 'intertype', 'Ot', 'execSuccess', 'syncComponent', 'anchors', 'linkmenu', 'output', 'reload'] // 閫夐」鍒楄〃
diff --git a/src/menu/components/form/formaction/formconfig.jsx b/src/menu/components/form/formaction/formconfig.jsx
index 2e98dbc..e90047a 100644
--- a/src/menu/components/form/formaction/formconfig.jsx
+++ b/src/menu/components/form/formaction/formconfig.jsx
@@ -14,6 +14,8 @@
     _type = '涓嬩竴姝�'
   } else if (card.type === 'close') {
     _type = '鍏抽棴'
+  } else if (card.type === 'reset') {
+    _type = '閲嶇疆'
   }
 
   let menulist = []
diff --git a/src/menu/components/form/formaction/index.jsx b/src/menu/components/form/formaction/index.jsx
index 50fae57..015c25e 100644
--- a/src/menu/components/form/formaction/index.jsx
+++ b/src/menu/components/form/formaction/index.jsx
@@ -65,6 +65,8 @@
       group.nextButton.style = style
     } else if (card.type === 'close') {
       group.closeButton.style = style
+    } else if (card.type === 'reset') {
+      group.resetButton.style = style
     }
 
     this.props.updateconfig(group)
@@ -148,6 +150,9 @@
       } else if (res.type === 'close') {
         res.enable = group.closeButton.enable || 'true'
         group.closeButton = res
+      } else if (res.type === 'reset') {
+        res.enable = group.resetButton.enable || 'true'
+        group.resetButton = res
       }
 
       this.setState({
@@ -220,13 +225,21 @@
         } trigger="hover">
           <Button type="link" className="submit mk-primary" onDoubleClick={this.changeMenu} style={resetStyle(group.subButton.style)}>{group.subButton.label}</Button>
         </Popover>
+        {group.resetButton && group.resetButton.enable === 'true' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <EditOutlined className="edit" title="缂栬緫" onClick={() => this.handleAction(group.resetButton)} />
+            <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.handleStyle(group.resetButton)}/>
+          </div>
+        } trigger="hover">
+          <Button type="link" className="reset" style={resetStyle(group.resetButton.style)}>{group.resetButton.label}</Button>
+        </Popover> : null}
         {group.closeButton && group.closeButton.enable === 'true' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
             <EditOutlined className="edit" title="缂栬緫" onClick={() => this.handleAction(group.closeButton)} />
             <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.handleStyle(group.closeButton)}/>
           </div>
         } trigger="hover">
-          <Button type="link" style={resetStyle(group.closeButton.style)}>{group.closeButton.label}</Button>
+          <Button type="link" className="reset" style={resetStyle(group.closeButton.style)}>{group.closeButton.label}</Button>
         </Popover> : null}
         {group.nextButton && group.nextButton.enable === 'true' ? <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
diff --git a/src/menu/components/form/formaction/index.scss b/src/menu/components/form/formaction/index.scss
index b980900..960834f 100644
--- a/src/menu/components/form/formaction/index.scss
+++ b/src/menu/components/form/formaction/index.scss
@@ -18,4 +18,7 @@
     height: auto;
     right: 0px;
   }
+  .reset {
+    height: auto;
+  }
 }
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 15527e3..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({
@@ -523,6 +487,7 @@
 
     res.enable = buttons.includes('enable') ? 'true' : 'false'
     res.closeEnable = buttons.includes('closeEnable') ? 'true' : 'false'
+    res.resetEnable = buttons.includes('resetEnable') ? 'true' : 'false'
 
     _card.wrap = res
 
@@ -546,6 +511,11 @@
     } else if (_card.subcards[0].closeButton) {
       _card.subcards[0].closeButton.enable = _card.wrap.closeEnable
     }
+    if (_card.wrap.resetEnable === 'true' && !_card.subcards[0].resetButton) {
+      _card.subcards[0].resetButton = {label: '閲嶇疆', enable: 'true', type: 'reset', style: {backgroundColor: '#ffffff', color: 'rgba(0,0,0,0.65)', borderColor: '#d9d9d9', borderWidth: '1px', paddingLeft: '25px', paddingRight: '25px', paddingTop: '5px', paddingBottom: '5px', marginLeft: '10px'}}
+    } else if (_card.subcards[0].resetButton) {
+      _card.subcards[0].resetButton.enable = _card.wrap.resetEnable
+    }
 
     this.updateComponent(_card)
   }
diff --git a/src/menu/components/form/simple-form/options.jsx b/src/menu/components/form/simple-form/options.jsx
index 1ace5c6..9df9c00 100644
--- a/src/menu/components/form/simple-form/options.jsx
+++ b/src/menu/components/form/simple-form/options.jsx
@@ -53,6 +53,9 @@
   if (wrap.closeEnable === 'true') {
     buttons.push('closeEnable')
   }
+  if (wrap.resetEnable === 'true') {
+    buttons.push('resetEnable')
+  }
 
   const wrapForm = [
     {
@@ -152,6 +155,7 @@
       required: false,
       options: [
         {value: 'enable', label: '鎻愪氦'},
+        {value: 'resetEnable', label: '閲嶇疆'},
         {value: 'closeEnable', label: '鍏抽棴'},
       ],
     },
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/markcomponent/index.jsx b/src/menu/components/share/markcomponent/index.jsx
index 246f2ea..f198d58 100644
--- a/src/menu/components/share/markcomponent/index.jsx
+++ b/src/menu/components/share/markcomponent/index.jsx
@@ -118,7 +118,21 @@
             'line-through': '涓垝绾�',
             'icon': '鍥炬爣',
             'iconfront': '鍥炬爣',
-            'iconback': '鍥炬爣',
+            'iconback': '鍥炬爣'
+          }
+
+          if (text[0] === 'indent') {
+            return (
+              <div>缂╄繘/{text[1]}涓瓧绗�</div>
+            )
+          } else if (text[0] === 'pointfront') {
+            return (
+              <div><span style={{display: 'inline-block', width: '8px', height: '8px', borderRadius: '14px', background: 'black', verticalAlign: 'middle'}}></span> 鐐癸紙鍓嶏級</div>
+            )
+          } else if (text[0] === 'pointback') {
+            return (
+              <div>鐐癸紙鍚庯級 <span style={{display: 'inline-block', width: '8px', height: '8px', borderRadius: '14px', background: 'black', verticalAlign: 'middle'}}></span></div>
+            )
           }
 
           return (
@@ -249,6 +263,7 @@
         })
       }
     ]
+
     let signs = [
       {
         value: 'font',
@@ -267,6 +282,14 @@
         label: '涓垝绾�'
       },
       {
+        value: 'pointfront',
+        label: '鐐癸紙鍓嶏級'
+      },
+      {
+        value: 'pointback',
+        label: '鐐癸紙鍚庯級'
+      },
+      {
         value: 'iconfront',
         label: '鍥炬爣锛堝墠锛�',
         children: icons
@@ -275,12 +298,32 @@
         value: 'iconback',
         label: '鍥炬爣锛堝悗锛�',
         children: icons
+      },
+      {
+        value: 'indent',
+        label: '缂╄繘',
+        children: [{
+          value: 2,
+          label: '2涓瓧绗�'
+        }, {
+          value: 4,
+          label: '4涓瓧绗�'
+        }, {
+          value: 6,
+          label: '6涓瓧绗�'
+        }, {
+          value: 8,
+          label: '8涓瓧绗�'
+        }]
       }
     ]
 
     if (type === 'line' || type === 'sequence') {
       signs.pop()
       signs.pop()
+      signs.pop()
+      signs.pop()
+      signs.pop()
     } else if (type === 'slider') {
       markColumns = markColumns.filter(col => {
         col.width = '20%'
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/share/sourcecomponent/index.jsx b/src/menu/components/share/sourcecomponent/index.jsx
index bf42033..fe17598 100644
--- a/src/menu/components/share/sourcecomponent/index.jsx
+++ b/src/menu/components/share/sourcecomponent/index.jsx
@@ -88,7 +88,7 @@
         </div> : null}
         <Modal
           visible={!!visible}
-          width={visible !== 'system' ? 600 : 1000}
+          width={visible !== 'system' ? 650 : 1000}
           closable={false}
           maskClosable={false}
           okText="纭畾"
diff --git a/src/menu/components/share/sourcecomponent/inputform/index.jsx b/src/menu/components/share/sourcecomponent/inputform/index.jsx
index 5f552ce..0a06300 100644
--- a/src/menu/components/share/sourcecomponent/inputform/index.jsx
+++ b/src/menu/components/share/sourcecomponent/inputform/index.jsx
@@ -174,7 +174,7 @@
     
     return (
       <div className="mk-source-pop-wrap">
-        {keyword === 'input' ? <Form.Item label="鍦板潃" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={{xs: { span: 24 }, sm: { span: 20 }}}>
+        {keyword === 'input' ? <Form.Item label="鍦板潃" help="鍙娇鐢ˊmywebsite@浠f浛鍩熷悕锛堝惈铏氭嫙鐩綍锛夛紝濡傦細@mywebsite@/Content/images/xxx.jpg" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={{xs: { span: 24 }, sm: { span: 20 }}}>
           <TextArea id="source-input" value={url} rows={4} onChange={this.changeValue}/>
         </Form.Item> : null}
         {keyword === 'upload' ? <Form.Item label="涓婁紶" labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={{xs: { span: 24 }, sm: { span: 20 }}}>
diff --git a/src/menu/components/share/sourcecomponent/inputform/index.scss b/src/menu/components/share/sourcecomponent/inputform/index.scss
index 576da5d..fc5b77f 100644
--- a/src/menu/components/share/sourcecomponent/inputform/index.scss
+++ b/src/menu/components/share/sourcecomponent/inputform/index.scss
@@ -50,6 +50,10 @@
     position: relative;
     top: -15px;
   }
+  .ant-form-explain {
+    margin-top: 5px;
+    word-break: break-all;
+  }
 }
 .picture-edit-model {
   .ant-modal {
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/columns/index.jsx b/src/menu/components/table/base-table/columns/index.jsx
index 1205028..aad0434 100644
--- a/src/menu/components/table/base-table/columns/index.jsx
+++ b/src/menu/components/table/base-table/columns/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { DndProvider, DragSource, DropTarget } from 'react-dnd'
-import { Table, Popover, Modal, message, notification } from 'antd'
+import { Table, Popover, Modal, message, notification, Typography } from 'antd'
 import { PlusOutlined, PlusSquareOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
@@ -12,6 +12,7 @@
 import './index.scss'
 
 const { confirm } = Modal
+const { Paragraph } = Typography
 const EditColumn = asyncComponent(() => import('./editColumn'))
 const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
 const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
@@ -199,7 +200,7 @@
       }
       return (
         <td style={{...style}} className={className}>
-          {val}
+          {column.field ? <Paragraph className="col-copy" copyable={{ text: column.field }}>{val}</Paragraph> : val}
           {column.Hide === 'true' ? <CloseCircleOutlined style={{marginLeft: '5px', color: 'orange', fontSize: '12px'}}/> : null}
           {column.marks && column.marks.length ? <AntDesignOutlined className="profile"/> : null}
         </td>
diff --git a/src/menu/components/table/base-table/columns/index.scss b/src/menu/components/table/base-table/columns/index.scss
index 45da4dc..48aae5d 100644
--- a/src/menu/components/table/base-table/columns/index.scss
+++ b/src/menu/components/table/base-table/columns/index.scss
@@ -23,6 +23,25 @@
     tr {
       td {
         background: #ffffff;
+        .col-copy {
+          margin-bottom: 0;
+          display: inline-block;
+          color: inherit;
+          .ant-typography-copy {
+            position: absolute;
+            left: 2px;
+            top: 0px;
+            margin-left: 0px;
+            font-size: 12px;
+            opacity: 0;
+            transition: opacity 0.2s;
+          }
+        }
+      }
+      td:hover .col-copy {
+        .ant-typography-copy {
+          opacity: 1;
+        }
       }
       td:not(.ant-table-selection-column) {
         position: relative;
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 00f61c5..cae43f6 100644
--- a/src/menu/components/table/normal-table/columns/index.jsx
+++ b/src/menu/components/table/normal-table/columns/index.jsx
@@ -12,7 +12,7 @@
 import './index.scss'
 
 const { confirm } = Modal
-const { Paragraph } = Typography 
+const { Paragraph } = Typography
 const EditColumn = asyncComponent(() => import('./editColumn'))
 const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
 const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
@@ -35,6 +35,32 @@
   updateMarks = (vals) => {
     const { column } = this.props
     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) {
@@ -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/index.jsx b/src/menu/datasource/index.jsx
index 759e84e..68edece 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -157,13 +157,15 @@
 
       if (res.columns) {
         res.columns = res.columns.map(item => {
-    
           if (/int/ig.test(item.datatype)) {
             item.type = 'number'
             item.decimal = 0
           } else if (/Decimal/ig.test(item.datatype)) {
             item.type = 'number'
             item.decimal = +item.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '')
+          } else if (/^date/ig.test(item.datatype)) {
+            item.type = 'text'
+            item.fieldlength = 50
           } else {
             item.type = 'text'
             item.fieldlength = +item.datatype.replace(/^Nvarchar\(/ig, '').replace(/\)/ig, '')
@@ -211,6 +213,23 @@
       if (config.subtype !== 'dualdatacard') {
         delete res.subColumns
       } else {
+        res.subColumns = res.subColumns.map(item => {
+          if (/int/ig.test(item.datatype)) {
+            item.type = 'number'
+            item.decimal = 0
+          } else if (/Decimal/ig.test(item.datatype)) {
+            item.type = 'number'
+            item.decimal = +item.datatype.replace(/^Decimal\(18,/ig, '').replace(/\)/ig, '')
+          } else if (/^date/ig.test(item.datatype)) {
+            item.type = 'text'
+            item.fieldlength = 50
+          } else {
+            item.type = 'text'
+            item.fieldlength = +item.datatype.replace(/^Nvarchar\(/ig, '').replace(/\)/ig, '')
+          }
+          return item
+        })
+  
         res.subColumns.reverse()
       }
 
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 7519b71..1ef5833 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { fromJS } from 'immutable'
 import { Form, Tabs, Popconfirm, notification, Modal, Typography, Spin, message, Button, Input } from 'antd'
-import { StopOutlined, CheckCircleOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined, BorderOutlined, SnippetsOutlined } from '@ant-design/icons'
+import { StopOutlined, CheckCircleOutlined, TableOutlined, EditOutlined, SwapOutlined, DeleteOutlined, CopyOutlined, BorderOutlined, SnippetsOutlined } from '@ant-design/icons'
 import moment from 'moment'
 import md5 from 'md5'
 
@@ -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,
@@ -1053,7 +1102,7 @@
             <EditTable actions={['edit', 'move', 'copy', 'del', 'clear']} searchKey={searchKey} type="datasourcefield" wrappedComponentRef={(inst) => this.datasource = inst} data={columns} columns={colColumns} onChange={(columns) => this.setState({columns})}/>
           </TabPane> : <TabPane tab={
             <span>
-              瀛楁闆�
+              瀛楁闆�<TableOutlined style={{marginLeft: '5px', fontSize: '12px'}} />
               {columns.length ? <span className="count-tip">{columns.length}</span> : null}
             </span>
           } key="columns">
@@ -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/debug/index.jsx b/src/menu/debug/index.jsx
index 6e18351..91b7f27 100644
--- a/src/menu/debug/index.jsx
+++ b/src/menu/debug/index.jsx
@@ -315,7 +315,7 @@
   
             card.backElements.forEach(cell => {
               if (cell.eleType !== 'button' || cell.hidden === 'true') return
-              let sql = this.resetButton(item, cell, process)
+              let sql = this.resetButton(item, cell, process, null, true)
 
               if (sql) {
                 if (typeof(sql) === 'string') {
@@ -364,11 +364,18 @@
     })
   }
 
-  resetButton = (item, cell, process, group) => {
+  resetButton = (item, cell, process, group, isback) => {
     let sql = ''
     if (['exec', 'prompt', 'pop', 'form', 'formSubmit'].includes(cell.OpenType)) {
       if (cell.intertype === 'system' || cell.procMode === 'system') { // 绯荤粺鎺ュ彛
-        sql = this.getSysDefaultSql(cell, item, process, group)
+        if (item.subtype === 'dualdatacard' && isback) {
+          let _item = fromJS(item).toJS()
+          _item.columns = _item.subColumns || []
+          _item.setting.primaryKey = _item.setting.subKey
+          sql = this.getSysDefaultSql(cell, _item, process, group)
+        } else {
+          sql = this.getSysDefaultSql(cell, item, process, group)
+        }
       }
     } else if (cell.OpenType === 'excelIn') {
       if (cell.intertype === 'system') {
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/card/cardcellList/index.jsx b/src/tabviews/custom/components/card/cardcellList/index.jsx
index c363313..58d36b8 100644
--- a/src/tabviews/custom/components/card/cardcellList/index.jsx
+++ b/src/tabviews/custom/components/card/cardcellList/index.jsx
@@ -426,6 +426,14 @@
             } else {
               val = <span>{val} <MkIcon style={mark.innerStyle} type={mark.icon} /></span>
             }
+          } else if (mark.space) {
+            val = <><span style={{float: 'left'}} dangerouslySetInnerHTML={{__html: mark.space}}></span>{val}</>
+          } else if (mark.point) {
+            if (mark.position === 'front') {
+              val = <>{mark.point}{val}</>
+            } else {
+              val = <>{val}{mark.point}</>
+            }
           }
           className = mark.signType
         }
@@ -507,6 +515,14 @@
               val = <span><MkIcon style={mark.innerStyle} type={mark.icon} /> {val}</span>
             } else {
               val = <span>{val} <MkIcon style={mark.innerStyle} type={mark.icon} /></span>
+            }
+          } else if (mark.space) {
+            val = <><span style={{float: 'left'}} dangerouslySetInnerHTML={{__html: mark.space}}></span>{val}</>
+          } else if (mark.point) {
+            if (mark.position === 'front') {
+              val = <>{mark.point}{val}</>
+            } else {
+              val = <>{val}{mark.point}</>
             }
           }
           className = mark.signType
@@ -774,9 +790,7 @@
             let func = new Function('data', card.formula)
             val = func(_data)
           } catch (e) {
-            if (window.GLOB.debugger === true) {
-              console.warn(e)
-            }
+            console.warn(e)
             val = ''
           }
         } else if (card.$sync) {
@@ -794,10 +808,8 @@
                 // eslint-disable-next-line
                 _val = eval(_val)
               } catch (e) {
-                if (window.GLOB.debugger === true) {
-                  console.info(_val)
-                  console.warn(e)
-                }
+                console.info(_val)
+                console.warn(e)
                 _val = 0
               }
             }
@@ -820,10 +832,8 @@
               // eslint-disable-next-line
               _val = eval(_val)
             } catch (e) {
-              if (window.GLOB.debugger === true) {
-                console.info(_val)
-                console.warn(e)
-              }
+              console.info(_val)
+              console.warn(e)
               _val = ''
             }
           }
@@ -882,6 +892,14 @@
             } else {
               val = <span>{val} <MkIcon style={mark.innerStyle} type={mark.icon} /></span>
             }
+          } else if (mark.space) {
+            val = <><span style={{float: 'left'}} dangerouslySetInnerHTML={{__html: mark.space}}></span>{val}</>
+          } else if (mark.point) {
+            if (mark.position === 'front') {
+              val = <>{mark.point}{val}</>
+            } else {
+              val = <>{val}{mark.point}</>
+            }
           }
           className = mark.signType
         }
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.jsx b/src/tabviews/custom/components/chart/antv-X6/index.jsx
index 97525bc..faedfd9 100644
--- a/src/tabviews/custom/components/chart/antv-X6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/index.jsx
@@ -989,7 +989,7 @@
     })
     graph.on('edge:click', ({ edge }) => {
       this.selectNode = edge
-      
+
       this.setState({node: edge.store.data})
 
       graph.clearTransformWidgets()
@@ -1561,19 +1561,41 @@
       let start_num = 0
       let end_num = 0
       let unvalid = false
+      let map = new Map()
+      let appMap = new Map()
       
       nodes.cells.forEach(item => {
-        if (item.mknode === 'start') {
+        if (item.shape === 'mk-text' || item.shape === 'lane') return
+
+        if (!item.mkdata) {
+          unvalid = true
+        } else if (item.mknode === 'start') {
           start_num++
         } else if (item.mknode === 'end') {
           end_num++
-        } else if (item.shape === 'edge' && item.mknode !== 'endEdge' && item.mknode !== 'startEdge') {
-          if (!item.mkdata.members || item.mkdata.members.length === 0) {
+        } else if (item.shape === 'edge') {
+          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
             unvalid = true
+          } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
+            if (map.has(item.source.cell)) {
+              unvalid = true
+            } else {
+              map.set(item.source.cell, true)
+            }
+          } else if (item.mkdata.flowType === 'approval' || item.mknode === 'endEdge') {
+            let val = ''
+            if (item.mkdata.execCondition === 'open') {
+              val = item.mkdata.match + item.mkdata.matchVal
+            }
+            if (appMap.has(item.source.cell + val)) {
+              unvalid = true
+            } else {
+              appMap.set(item.source.cell + val, true)
+            }
           }
         }
-
       })
+
       if (start_num !== 1 || end_num !== 1 || unvalid) {
         _status = 0
       }
@@ -1993,15 +2015,49 @@
       let start_num = 0
       let end_num = 0
       let unvalidId = ''
-      
+      let emptyNode = null
+      let emptyEdge = null
+      let map = new Map()
+      let appMap = new Map()
+      let rejectId = ''
+      let approvalId = ''
+
       nodes.cells.forEach(item => {
-        if (item.mknode === 'start') {
+        if (item.shape === 'mk-text' || item.shape === 'lane') return
+
+        if (!item.mkdata) {
+          if (item.shape !== 'edge') {
+            if (!emptyNode) {
+              emptyNode = item
+            }
+          } else {
+            if (!emptyEdge) {
+              emptyEdge = item
+            }
+          }
+        } else if (item.mknode === 'start') {
           start_num++
         } else if (item.mknode === 'end') {
           end_num++
-        } else if (item.shape === 'edge' && item.mknode !== 'endEdge' && item.mknode !== 'startEdge') {
-          if (!item.mkdata.members || item.mkdata.members.length === 0) {
+        } else if (item.shape === 'edge' && !unvalidId && !rejectId && !approvalId) {
+          if (item.mknode !== 'endEdge' && item.mknode !== 'startEdge' && (!item.mkdata.members || item.mkdata.members.length === 0)) {
             unvalidId = item.id
+          } else if (item.mknode === 'startEdge' || item.mkdata.flowType === 'reject') {
+            if (map.has(item.source.cell)) {
+              rejectId = item.source.cell
+            } else {
+              map.set(item.source.cell, true)
+            }
+          } else if (item.mkdata.flowType === 'approval' || item.mknode === 'endEdge') {
+            let val = ''
+            if (item.mkdata.execCondition === 'open') {
+              val = item.mkdata.match + item.mkdata.matchVal
+            }
+            if (appMap.has(item.source.cell + val)) {
+              approvalId = item.source.cell
+            } else {
+              appMap.set(item.source.cell + val, item)
+            }
           }
         }
       })
@@ -2030,21 +2086,97 @@
           message: '缁撴潫鑺傜偣涓嶅彲娣诲姞澶氫釜锛�',
           duration: 2
         })
-      } else if (unvalidId) {
-        let edge = this.mkGraph.getCellById(unvalidId)
+      } else if (emptyNode) {
+        let errmsg = '閮ㄥ垎鑺傜偣鏈缃熀鏈俊鎭��'
+        if (emptyNode.attrs && emptyNode.attrs.text && emptyNode.attrs.text.text) {
+          errmsg = '鑺傜偣銆�' + emptyNode.attrs.text.text + '銆嬫湭璁剧疆鍩烘湰淇℃伅銆�'
+        }
+        notification.warning({
+          top: 92,
+          message: errmsg,
+          duration: 2
+        })
+      } else if (emptyEdge) {
+        let errmsg = '閮ㄥ垎杩炵嚎鏈缃熀鏈俊鎭��'
 
-        let node = edge.getTargetCell()
+        let edge = this.mkGraph.getCellById(emptyEdge.id)
+        let target = edge.getTargetCell()
+
+        let t_label = ''
+        if (target.attrs && target.attrs.text && target.attrs.text.text) {
+          t_label = target.attrs.text.text
+        }
+
+        let source = edge.getSourceCell()
+
+        let s_label = ''
+        if (source.attrs && source.attrs.text && source.attrs.text.text) {
+          s_label = source.attrs.text.text
+        }
+
+        if (t_label && s_label) {
+          errmsg = '鑺傜偣銆�' + s_label + '銆嬩笌鑺傜偣銆�' + t_label + '銆嬮棿杩炵嚎鏈缃熀鏈俊鎭��'
+        }
+
+        notification.warning({
+          top: 92,
+          message: errmsg,
+          duration: 2
+        })
+      } else if (rejectId) {
+        let node = this.mkGraph.getCellById(rejectId)
 
         let title = ''
-        if (node.attrs && node.attrs.text) {
-          title = node.attrs.text.text + ''
+        if (node.attrs && node.attrs.text && node.attrs.text.text) {
+          title = '鑺傜偣銆�' + node.attrs.text.text + '銆�'
         } else if (node.mkdata) {
           title = '鐘舵�侊細' + node.mkdata.status + ' - ' + node.mkdata.statusName
         }
 
         notification.warning({
           top: 92,
-          message: '杩炴帴锛�' + title + '锛夌殑绾挎湭璁剧疆瀹℃壒浜猴紒',
+          message: title + ' 涓嶅彲璁剧疆涓ゆ潯椹冲洖杩炵嚎锛�',
+          duration: 2
+        })
+      } else if (approvalId) {
+        let node = this.mkGraph.getCellById(approvalId)
+
+        let title = ''
+        if (node.attrs && node.attrs.text && node.attrs.text.text) {
+          title = '鑺傜偣銆�' + node.attrs.text.text + '銆�'
+        } else if (node.mkdata) {
+          title = '鐘舵�侊細' + node.mkdata.status + ' - ' + node.mkdata.statusName
+        }
+
+        notification.warning({
+          top: 92,
+          message: title + ' 鍚庣殑瀹℃壒鍒嗘敮鎵ц鏉′欢閲嶅锛�',
+          duration: 2
+        })
+      } else if (unvalidId) {
+        let edge = this.mkGraph.getCellById(unvalidId)
+
+        let node = edge.getTargetCell()
+
+        let title = ''
+        if (node.attrs && node.attrs.text && node.attrs.text.text) {
+          title = node.attrs.text.text
+        } else if (node.mkdata) {
+          title = '鐘舵�侊細' + node.mkdata.status + ' - ' + node.mkdata.statusName
+        }
+
+        let source = edge.getSourceCell()
+
+        let s_label = ''
+        if (source.attrs && source.attrs.text && source.attrs.text.text) {
+          s_label = source.attrs.text.text
+        } else if (source.mkdata) {
+          s_label = '鐘舵�侊細' + source.mkdata.status + ' - ' + source.mkdata.statusName
+        }
+
+        notification.warning({
+          top: 92,
+          message: '鑺傜偣銆�' + s_label + '銆嬩笌銆�' + title + '銆嬮棿杩炵嚎鏈缃鎵逛汉锛�',
           duration: 2
         })
       } else {
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
index bf50398..9ff4eb4 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.jsx
@@ -499,7 +499,7 @@
           visible={visible}
           closable={false}
           maskClosable={false}
-          width={1000}
+          width={1050}
           onOk={this.confirm}
           onCancel={() => this.setState({visible: false})}
           destroyOnClose
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
index 893aaf2..a161a64 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/index.scss
@@ -130,6 +130,7 @@
     background-image: none;
     border: 1px solid #d9d9d9;
     border-radius: 4px;
+    vertical-align: middle;
 
     .anticon-form {
       float: right;
@@ -170,6 +171,13 @@
       }
     }
   }
+  .ant-transfer-operation {
+    margin: 0 15px;
+
+    .ant-btn:first-child {
+      margin-bottom: 10px;
+    }
+  }
 }
 
 .member-modal {
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
index 65f565d..0d89461 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/memberform.jsx
@@ -175,7 +175,7 @@
 
     return (
       <>
-        <div className="member-input">{value.length}浜�<FormOutlined onClick={this.trigger} /></div>
+        <div className="member-input">{value.length > 0 ? value.length + '浜�' : ''}<FormOutlined onClick={this.trigger} /></div>
         <Modal
           wrapClassName="member-modal"
           title="閫夋嫨浜哄憳"
diff --git a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
index 4d6fc81..6444785 100644
--- a/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/nodeupdate/nodeform.jsx
@@ -1,6 +1,6 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Tooltip, InputNumber } from 'antd'
+import { Form, Row, Col, Input, Radio, Tooltip, InputNumber, Switch } from 'antd'
 import { QuestionCircleOutlined } from '@ant-design/icons'
 
 import MemberForm from './memberform'
@@ -14,13 +14,23 @@
   }
 
   state = {
-    flowType: this.props.data.flowType || 'approval'
+    flowType: this.props.data.flowType || 'approval',
+    execCondition: this.props.data.execCondition === 'open',
   }
 
   handleConfirm = () => {
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
         if (!err) {
+          if (values.execCondition === true) {
+            values.execCondition = 'open'
+          } else if (values.execCondition === false) {
+            values.execCondition = 'close'
+          }
+
+          if (values.matchVal) {
+            values.matchVal = values.matchVal.replace(/\t+|\v+|\s+/g, '')
+          }
           resolve(values)
         } else {
           reject(err)
@@ -32,7 +42,7 @@
   render() {
     const { node, orgs } = this.props
     const { getFieldDecorator } = this.props.form
-    const { flowType } = this.state
+    const { flowType, execCondition } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -155,6 +165,60 @@
               )}
             </Form.Item>
           </Col> : null}
+          {nodetype === 'edge' && flowType !== 'reject' ? <Col span={12}>
+            <Form.Item label="鎵ц鏉′欢">
+              {getFieldDecorator('execCondition', {
+                valuePropName: 'checked',
+                initialValue: execCondition
+              })(
+                <Switch checkedChildren="寮�鍚�" unCheckedChildren="鍏抽棴" onChange={(val) => this.setState({execCondition: val})} />
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' && flowType !== 'reject' && execCondition ? <Col span={12}>
+            <Form.Item label="瀵规瘮鏂瑰紡">
+              {getFieldDecorator('match', {
+                initialValue: data.match || '='
+              })(
+                <Radio.Group>
+                  <Radio value="=">=</Radio>
+                  <Radio value="<">&lt;</Radio>
+                  <Radio value=">">&gt;</Radio>
+                  <Radio value="<=">&lt;=</Radio>
+                  <Radio value=">=">&gt;=</Radio>
+                  <Radio value="!=">!=</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'edge' && flowType !== 'reject' && execCondition ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="瀵规瘮鍊间腑涓嶅彲鍖呭惈鍒惰〃绗︺�佺┖鏍笺�佹崲琛岀绛夈��">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                瀵规瘮鍊�
+              </Tooltip>
+            }>
+              {getFieldDecorator('matchVal', {
+                initialValue: data.matchVal || ''
+              })(
+                <Input placeholder="" autoComplete="off"/>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {nodetype === 'node' ? <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鏍囪灏嗕綔涓鸿妭鐐笽D">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                鏍囪
+              </Tooltip>
+            }>
+              {getFieldDecorator('sign', {
+                initialValue: data.sign || ''
+              })(
+                <Input placeholder="" autoComplete="off"/>
+              )}
+            </Form.Item>
+          </Col> : null}
           <Col span={24}>
             <Form.Item label="澶囨敞">
               {getFieldDecorator('remark', {
diff --git a/src/tabviews/custom/components/form/simple-form/index.jsx b/src/tabviews/custom/components/form/simple-form/index.jsx
index 8115aea..5b3c32c 100644
--- a/src/tabviews/custom/components/form/simple-form/index.jsx
+++ b/src/tabviews/custom/components/form/simple-form/index.jsx
@@ -63,7 +63,7 @@
 
     let _group = _config.subcards[0]
 
-    if (_group.subButton.enable === 'false' && (!_group.closeButton || _group.closeButton.enable !== 'true')) {
+    if (_group.subButton.enable === 'false' && (!_group.closeButton || _group.closeButton.enable !== 'true') && (!_group.resetButton || _group.resetButton.enable !== 'true')) {
       _group.subButton.style.display = 'none'
       _group.$button = 'no-button'
     }
@@ -318,6 +318,16 @@
     MKEmitter.emit('closeTabView', group.subButton.$MenuID)
   }
 
+  resetTab = () => {
+    const { data } = this.state
+
+    this.setState({
+      data: null
+    }, () => {
+      this.setState({data: data})
+    })
+  }
+
   render() {
     const { config, loading, BID, BData, data, group } = this.state
 
@@ -350,6 +360,7 @@
             columns={config.columns}
             selectedData={data.$$empty ? [] : [data]}
           />
+          {group.resetButton && group.resetButton.enable === 'true' ? <Button type="link" onClick={this.resetTab} style={group.resetButton.style}>{group.resetButton.label}</Button> : null}
           {group.closeButton && group.closeButton.enable === 'true' ? <Button type="link" onClick={this.closeTab} style={group.closeButton.style}>{group.closeButton.label}</Button> : null}
         </div> : null}
       </div>
diff --git a/src/tabviews/custom/components/module/account/index.jsx b/src/tabviews/custom/components/module/account/index.jsx
index 24d04ca..bdc02be 100644
--- a/src/tabviews/custom/components/module/account/index.jsx
+++ b/src/tabviews/custom/components/module/account/index.jsx
@@ -120,10 +120,12 @@
   }
 
   setBook = (item, resolve) => {
+    const { config } = this.props
+
     if (!resolve) {
       this.setState({activeItem: item})
   
-      MKEmitter.emit('resetSelectLine', this.props.config.uuid, item.id, item)
+      MKEmitter.emit('resetSelectLine', config.uuid, item.id, item)
     }
     
     let userid = sessionStorage.getItem('UserID') || ''
@@ -152,6 +154,7 @@
       }
 
       if (resolve) {
+        sessionStorage.setItem('ThirdMenu', config.$pageId)
         window.location.reload()
       }
     })
diff --git a/src/tabviews/custom/components/share/normalTable/index.jsx b/src/tabviews/custom/components/share/normalTable/index.jsx
index 90c6088..be531d2 100644
--- a/src/tabviews/custom/components/share/normalTable/index.jsx
+++ b/src/tabviews/custom/components/share/normalTable/index.jsx
@@ -144,6 +144,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
       if (col.blur) {
@@ -208,6 +216,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
@@ -337,9 +353,7 @@
           let func = new Function('data', col.formula)
           content = func([record])
         } catch (e) {
-          if (window.GLOB.debugger === true) {
-            console.warn(e)
-          }
+          console.warn(e)
           content = ''
         }
       } else {
@@ -352,10 +366,8 @@
             // eslint-disable-next-line
             content = eval(content)
           } catch (e) {
-            if (window.GLOB.debugger === true) {
-              console.info(content)
-              console.warn(e)
-            }
+            console.info(content)
+            console.warn(e)
             content = ''
           }
   
@@ -389,6 +401,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
diff --git a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
index 4ce4d1b..0f95fec 100644
--- a/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
+++ b/src/tabviews/custom/components/table/edit-table/normalTable/index.jsx
@@ -309,6 +309,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
@@ -397,6 +405,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
@@ -441,9 +457,7 @@
           let func = new Function('data', col.formula)
           content = func([record])
         } catch (e) {
-          if (window.GLOB.debugger === true) {
-            console.warn(e)
-          }
+          console.warn(e)
           content = ''
         }
       } else {
@@ -457,10 +471,8 @@
             // eslint-disable-next-line
             content = eval(content)
           } catch (e) {
-            if (window.GLOB.debugger === true) {
-              console.info(content)
-              console.warn(e)
-            }
+            console.info(content)
+            console.warn(e)
             content = ''
           }
         }
@@ -498,6 +510,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
@@ -750,6 +770,14 @@
             }
           } else if (mark.innerStyle) {
             content = <span style={mark.innerStyle}>{content}</span>
+          } else if (mark.space) {
+            content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+          } else if (mark.point) {
+            if (mark.position === 'front') {
+              content = <>{mark.point}{content}</>
+            } else {
+              content = <>{content}{mark.point}</>
+            }
           }
         }
 
@@ -817,6 +845,14 @@
             }
           } else if (mark.innerStyle) {
             content = <span style={mark.innerStyle}>{content}</span>
+          } else if (mark.space) {
+            content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+          } else if (mark.point) {
+            if (mark.position === 'front') {
+              content = <>{mark.point}{content}</>
+            } else {
+              content = <>{content}{mark.point}</>
+            }
           }
         }
 
@@ -850,9 +886,7 @@
           let func = new Function('data', col.formula)
           content = func([record])
         } catch (e) {
-          if (window.GLOB.debugger === true) {
-            console.warn(e)
-          }
+          console.warn(e)
           content = ''
         }
       } else {
@@ -866,10 +900,8 @@
             // eslint-disable-next-line
             content = eval(content)
           } catch (e) {
-            if (window.GLOB.debugger === true) {
-              console.info(content)
-              console.warn(e)
-            }
+            console.info(content)
+            console.warn(e)
             content = ''
           }
         }
@@ -907,6 +939,14 @@
           }
         } else if (mark.innerStyle) {
           content = <span style={mark.innerStyle}>{content}</span>
+        } else if (mark.space) {
+          content = <><span dangerouslySetInnerHTML={{__html: mark.space}}></span>{content}</>
+        } else if (mark.point) {
+          if (mark.position === 'front') {
+            content = <>{mark.point}{content}</>
+          } else {
+            content = <>{content}{mark.point}</>
+          }
         }
       }
 
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index e4f0f5a..55cf1da 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -238,6 +238,15 @@
       config.$cache = config.cacheLocal === 'true'
       config.$time = config.localCacheTime || 0
 
+      if (window.GLOB.systemType !== 'production' && result.modifydate) {
+        let s = (new Date().getTime() - new Date(result.modifydate).getTime()) / (1000 * 60 * 60)
+        if (!isNaN(s) && s < 2) {
+          config.$cache = false
+          config.$time = 0
+          config.cacheUseful = 'false'
+        }
+      }
+
       let initInters = []
 
       config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters)
diff --git a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
index 30385fe..7e032ca 100644
--- a/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/exceloutbutton/index.jsx
@@ -447,7 +447,7 @@
     const { btn } = this.props
     
     let imgCol = false
-    let columns = btn.verify.columns.filter(col => {
+    let columns = btn.verify.columns.map(col => {
       if (col.type === 'image') {
         imgCol = true
       }
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 eeb24ce..4da4369 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -2882,7 +2882,19 @@
         _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
 
         if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
-          _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+          if (item.interception === 'func') {
+            try {
+              // eslint-disable-next-line
+              let func = new Function('value', 'data', item.func)
+              _item.value = func(_item.value, _data)
+              _item.value = _item.value !== undefined ? _item.value : ''
+            } catch (e) {
+              console.warn(e)
+              _item.value = ''
+            }
+          } else {
+            _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+          }
         }
         if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
           _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (BID || ''))
@@ -2996,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 6691220..b55792d 100644
--- a/src/tabviews/zshare/actionList/printbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/printbutton/index.jsx
@@ -2148,7 +2148,19 @@
         _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
 
         if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
-          _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+          if (item.interception === 'func') {
+            try {
+              // eslint-disable-next-line
+              let func = new Function('value', 'data', item.func)
+              _item.value = func(_item.value, _data)
+              _item.value = _item.value !== undefined ? _item.value : ''
+            } catch (e) {
+              console.warn(e)
+              _item.value = ''
+            }
+          } else {
+            _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+          }
         }
         if (_item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
           _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
@@ -2226,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 e4f95d3..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') {
@@ -1218,7 +1255,19 @@
             _item.value = _item.value.replace(/\t+|\v+/g, '')       // 鍘婚櫎鍒惰〃绗�
     
             if (item.interception !== 'false') {                    // 鍘婚櫎棣栧熬绌烘牸
-              _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+              if (item.interception === 'func') {
+                try {
+                  // eslint-disable-next-line
+                  let func = new Function('value', 'data', item.func)
+                  _item.value = func(_item.value, record)
+                  _item.value = _item.value !== undefined ? _item.value : ''
+                } catch (e) {
+                  console.warn(e)
+                  _item.value = ''
+                }
+              } else {
+                _item.value = _item.value.replace(/(^\s*|\s*$)/g, '')
+              }
             }
             if (item.type === 'text' && /@appkey@|@SessionUid@|@bid@/ig.test(_item.value)) { // 鐗规畩瀛楁鏇挎崲
               _item.value = _item.value.replace(/^(\s*)@appkey@(\s*)$/ig, window.GLOB.appkey).replace(/^(\s*)@SessionUid@(\s*)$/ig, (localStorage.getItem('SessionUid') || '')).replace(/^(\s*)@bid@(\s*)$/ig, (this.props.BID || ''))
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/actioncomponent/verifyexcelout/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
index 5b520c4..6555fcc 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/index.jsx
@@ -970,7 +970,7 @@
             <Button className="excel-col-add mk-red" title="娓呯┖Excel鍒�" onClick={this.clearField}>
               娓呯┖Excel鍒�
             </Button>
-            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>濡傞渶瀵煎嚭搴忓彿锛岃浣跨敤瀛楁 $Index锛涙暟鍊肩被鍨嬪鍑烘椂鍙繘琛屾暟鎹鐞嗭紙鍙栫粷瀵瑰�笺�佷繚鐣欏皬鏁颁綅锛夛紱绾㈣壊鏍囬瀵煎嚭鏃跺垪澶存枃瀛椾负绾㈣壊銆�</div>
+            <div style={{color: '#959595', fontSize: '13px', paddingLeft: '10px'}}>濡傞渶瀵煎嚭搴忓彿锛岃浣跨敤瀛楁 $Index锛涙暟鍊肩被鍨嬪鍑烘椂鍙彇缁濆鍊间互鍙婅缃皬鏁颁綅锛涘鍑轰负鍚︽椂锛屼笉浣跨敤琛屼俊鎭紱绾㈣壊鏍囬瀵煎嚭鏃跺垪澶存枃瀛椾负绾㈣壊銆�</div>
             <EditTable actions={['edit', 'move', 'copy', 'del']} type="excelcolumn" wrappedComponentRef={(inst) => this.columnRef = inst} data={verify.columns} columns={excelColumns} onChange={this.changeColumns}/>
           </TabPane>
           {card.intertype === 'system' ? <TabPane tab={
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
index 04b1446..20bb8e3 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelout/utils.jsx
@@ -67,14 +67,7 @@
     let custompage = /@pageSize@|@orderBy@/i.test(_dataresource + _customScript)
     
     // 姝e垯鏇挎崲
-    let _regoptions = regoptions.map(item => {
-      return {
-        reg: new RegExp('@' + item.key + '@', 'ig'),
-        value: `'0'`
-      }
-    })
-
-    _regoptions.push({
+    regoptions.push({
       reg: new RegExp('@orderBy@', 'ig'),
       value: verify.order
     }, {
@@ -85,7 +78,7 @@
       value: 1
     })
 
-    _regoptions.forEach(item => {
+    regoptions.forEach(item => {
       _dataresource = _dataresource.replace(item.reg, item.value)
       _customScript = _customScript.replace(item.reg, item.value)
       _tailScript = _tailScript.replace(item.reg, item.value)
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 752c7ec..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',
@@ -3615,16 +3899,28 @@
     {
       type: 'radio',
       key: 'interception',
-      label: '鎴彇绌烘牸',
+      label: '鎴彇鏂瑰紡',
       initVal: card.interception || 'true',
-      tooltip: '鎻愪氦鏃讹紝鏄惁鎴彇棣栧熬鐨勭┖鐧藉瓧绗︺��',
+      tooltip: '鎻愪氦鏃剁殑鏂囨湰澶勭悊鏂瑰紡锛岀┖鐧藉瓧绗︽寚寮�澶存垨缁撳熬鐨勭┖鐧藉瓧绗︺��',
       options: [{
-        value: 'true',
-        text: '鏄�'
-      }, {
         value: 'false',
-        text: '鍚�'
+        text: '鏃�'
+      }, {
+        value: 'true',
+        text: '绌虹櫧瀛楃'
+      }, {
+        value: 'func',
+        text: '鑷畾涔夊嚱鏁�'
       }]
+    },
+    {
+      type: 'textarea',
+      key: 'func',
+      label: '鍑芥暟',
+      initVal: card.func || '',
+      tooltip: '鍑芥暟鏈変袱涓叆鍙�(value, data)锛岀涓�涓负褰撳墠琛ㄥ崟鍊硷紝绗簩涓负琛ㄥ崟鎵�鏈夊瓧娈�-鍊肩殑瀵硅薄锛岃杩斿洖澶勭悊鍚庣殑鍊笺��',
+      rows: 2,
+      required: true
     },
     {
       type: 'textarea',
@@ -3858,7 +4154,7 @@
       type: 'radio',
       key: 'constant',
       label: 'Unicode甯搁噺',
-      tooltip: '浣跨敤鏃跺皢鍦ㄦ彁浜ゅ唴瀹瑰墠鍔犱笂 N锛屼唬琛ㄥ瓨鍏ユ暟鎹簱鏃朵互 Unicode 鏍煎紡瀛樺偍銆�',
+      tooltip: `浣跨敤鏃跺皢鍦ㄦ彁浜ゅ唴瀹瑰墠鍔犱笂 N锛屼唬琛ㄥ瓨鍏ユ暟鎹簱鏃朵互 Unicode 鏍煎紡瀛樺偍銆備緥濡傦細@nvarchar=N'脴W30041'銆俙,
       initVal: card.constant || 'false',
       options: [{
         value: 'true',
@@ -4004,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 be0389c..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']
 }
 
@@ -147,6 +148,9 @@
           shows.push('regularExtra')
         }
       }
+      if (this.record.interception === 'func') {
+        shows.push('func')
+      }
     } else if (type === 'number') {
       reTypes.initval = 'number'
       reRequired.initval = true
@@ -165,6 +169,9 @@
         shows.push('fieldlength')
       } else if (this.record.declare === 'decimal') {
         shows.push('decimal')
+      }
+      if (this.record.interception === 'func') {
+        shows.push('func')
       }
     } else if (['multiselect', 'select', 'link', 'radio', 'checkbox'].includes(type)) {
       if (this.record.resourceType === '0') {        // 鑷畾涔夎祫婧�
@@ -277,6 +284,9 @@
     } else if (type === 'textarea') {
       if (this.record.encryption === 'false') {
         shows.push('enterReplace')
+      }
+      if (this.record.interception === 'func') {
+        shows.push('func')
       }
     }
 
@@ -420,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
             })
           }
@@ -505,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) => {
@@ -627,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({
@@ -664,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 = [
@@ -681,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}
@@ -688,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>
@@ -769,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 = []
@@ -777,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
@@ -786,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 = [
@@ -827,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
       }
     })
@@ -868,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') {
@@ -1011,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/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index 6ea9c9e..83c366d 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -279,7 +279,7 @@
   }
 
   render() {
-    const { unionFields, verify, notes, card, appType } = this.props
+    const { unionFields, verify, notes, card, appType, columns } = this.props
     const { wxTemps, selectTemp } = this.state
     const formItemLayout = {
       labelCol: {
@@ -290,6 +290,17 @@
         xs: { span: 24 },
         sm: { span: 16 }
       }
+    }
+
+    let _columns = []
+    if (window.GLOB.process) {
+      _columns = columns.filter(col => {
+        if (!col.field) return false
+        if (col.field.toLowerCase() === 'id') return false
+        if (col.type === 'text' && col.fieldlength > 100)  return false
+  
+        return true
+      })
     }
 
     return (
@@ -462,6 +473,22 @@
               </Radio.Group>
             </Form.Item>
           </Col> : null}
+          {window.GLOB.process && verify.workFlow === 'true' && verify.flowType === 'approval' ? <Col span={8}>
+            <Form.Item label={
+              <Tooltip placement="bottomLeft" title="濡傛灉瀹℃壒瀛樺湪澶氭潯鍒嗘敮锛屽彲娣诲姞瀹℃壒娴佺▼鐨勬帶鍒跺瓧娈碉紝閫氳繃琛屼俊鎭帶鍒舵祦绋嬭蛋鍚戙�傛敞锛氶渶鍦ㄦ祦绋嬪浘涓畬鍠勫垎鏀殑鎵ц鏉′欢銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                娴佺▼鎺у埗
+              </Tooltip>
+            }>
+              <Select allowClear value={verify.flowBranch} onChange={(val) => {this.onOptionChange(val || '', 'flowBranch')}}>
+                {_columns.map(option =>
+                  <Select.Option key={option.field} value={option.field}>
+                    {option.label}
+                  </Select.Option>
+                )}
+              </Select>
+            </Form.Item>
+          </Col> : null}
           <Col span={24}></Col>
           <Col span={8}>
             <Form.Item label={
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 3103749..df7c6dc 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -626,7 +626,7 @@
       oriVerify: fromJS(_verify).toJS()
     })
 
-    if (config.Template !== 'FormTab' && card.intertype === 'inner') {
+    if (card.intertype === 'inner') {
       return
     }
 
@@ -637,11 +637,6 @@
           field: card.field,
           label: card.label,
           type: 'text'
-        })
-        resolve(_fields)
-      } else if (config.Template === 'FormTab') {
-        config.groups.forEach(group => {
-          _fields.push(...group.sublist)
         })
         resolve(_fields)
       } else if (card.modal && (card.OpenType === 'pop' || !card.OpenType)) {
@@ -1553,7 +1548,7 @@
   }
 
   render() {
-    const { card } = this.props
+    const { card, columns } = this.props
     const { activeKey, verifyInter, setting, verify, fields, uniqueFields, uniqueColumns, unionFields, onceUniqueColumns, columnsFields, contrastColumns, customColumns, orderColumns, scriptsColumns, cbScriptsColumns, orderModular, orderModularDetail, voucher, voucherDetail, notes, appType } = this.state
     const formItemLayout = {
       labelCol: {
@@ -1576,7 +1571,7 @@
               {verify.default === 'false' ? <span className="count-tip"><ExclamationOutlined style={{color: 'orange'}}/></span> : null}
             </span>
           } key="base">
-            <BaseForm card={card} appType={appType} unionFields={unionFields} setting={setting} verify={verify} notes={notes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
+            <BaseForm card={card} appType={appType} columns={columns} unionFields={unionFields} setting={setting} verify={verify} notes={notes} onChange={(verify) => this.setState({verify})} wrappedComponentRef={(inst) => this.baseForm = inst}/>
           </TabPane> : null}
           {verifyInter === 'system' ? <TabPane tab={
             <span>
@@ -1612,7 +1607,7 @@
               fields={fields}
               btn={this.props.card}
               billcodes={verify.billcodes}
-              columns={this.props.columns}
+              columns={columns}
               modular={orderModular}
               modularDetail={orderModularDetail}
               orderChange={this.orderChange}
@@ -1641,7 +1636,7 @@
           } key="voucher">
             <VoucherForm
               voucher={voucher}
-              columns={this.props.columns}
+              columns={columns}
               voucherobj={verify.voucher}
               voucherDetail={voucherDetail}
               voucherChange={this.voucherChange}
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index 59816a5..2af2a61 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -919,6 +919,13 @@
     if (item.setting && item.setting.supModule && item.setting.supModule[0] !== 'empty') {
       item.setting.supModule = ''
     }
+    
+    if (item.wrap && item.wrap.supType === 'multi') {
+      item.wrap.supType = 'single'
+
+      delete item.supNodes
+    }
+    
     if (item.wrap && item.wrap.supModule) {
       item.wrap.supModule = ''
     }
@@ -1546,6 +1553,11 @@
     } else if (card.type !== 'balcony' && !card.setting.supModule) {  // 鎮诞妗嗕笂绾х粍浠堕渶鍗曠嫭璁剧疆
       errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
     }
+    if (card.subtype === 'dualdatacard' && card.subColumns) {
+      card.subColumns.forEach(col => {
+        columns.push(col.field)
+      })
+    }
   } else if ((card.type === 'balcony' || card.type === 'card') && card.wrap.datatype === 'public') {
     columns = card.columns.map(c => c.field)
   }
@@ -1553,6 +1565,31 @@
   let doubleClick = ''
   if (card.type === 'table') {
     doubleClick = card.wrap.doubleClick || ''
+  }
+
+  let checkBtn = (cell) => {
+    if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+      if (!cell.modal || cell.modal.fields.length === 0) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+      }
+    } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
+      errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
+    } else if (cell.OpenType === 'excelOut') {
+      if (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0) {
+        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
+      } else if (cell.intertype === 'system' && cell.verify.dataType !== 'custom' && card.$c_ds && columns.length > 0) {
+        let cols = []
+        cell.verify.columns.forEach(col => {
+          if (col.output === 'false' || col.Column === '$Index') return
+          if (!columns.includes(col.Column)) {
+            cols.push(col.Column)
+          }
+        })
+        if (cols.length) {
+          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楋紙${cols.join('銆�')}锛夊湪瀛楁闆嗕腑涓嶅瓨鍦紒`})
+        }
+      }
+    }
   }
 
   if (card.$c_ac) {
@@ -1565,15 +1602,7 @@
       //     errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑寮圭獥鏍囩鏈惎鐢╜})
       //   }
       // }
-      if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-        if (!cell.modal || cell.modal.fields.length === 0) {
-          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-        }
-      } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
-        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
-      } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
-        errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-      }
+      checkBtn(cell)
       if (doubleClick === cell.uuid) {
         doubleClick = ''
       }
@@ -1586,15 +1615,7 @@
       item.elements.forEach(cell => {
         if (cell.eleType === 'button') {
           if (cell.hidden === 'true') return
-          if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-            if (!cell.modal || cell.modal.fields.length === 0) {
-              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-            }
-          } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
-            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
-          } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
-            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-          }
+          checkBtn(cell)
           if (linkbtn && linkbtn === cell.uuid) {
             linkbtn = ''
           }
@@ -1607,15 +1628,7 @@
         item.backElements.forEach(cell => {
           if (cell.eleType === 'button') {
             if (cell.hidden === 'true') return
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
-              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
-            } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
-              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-            }
+            checkBtn(cell)
             if (linkbtn && linkbtn === cell.uuid) {
               linkbtn = ''
             }
@@ -1639,15 +1652,7 @@
     card.elements.forEach(cell => {
       if (cell.eleType === 'button') {
         if (cell.hidden === 'true') return
-        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-          if (!cell.modal || cell.modal.fields.length === 0) {
-            errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-          }
-        } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
-          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
-        } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
-          errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-        }
+        checkBtn(cell)
       } else if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
         errors.push({ level: 1, detail: `鍗$墖涓姩鎬佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
       }
@@ -1660,15 +1665,8 @@
         col.elements.forEach(cell => {
           if (cell.eleType === 'button') {
             if (cell.hidden === 'true') return
-            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
-              if (!cell.modal || cell.modal.fields.length === 0) {
-                errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
-              }
-            } else if (cell.OpenType === 'excelIn' && (!cell.verify || !cell.verify.sheet || !cell.verify.columns || cell.verify.columns.length === 0)) {
-              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎叆鍒楁湭璁剧疆锛乣})
-            } else if (cell.OpenType === 'excelOut' && (!cell.verify || !cell.verify.columns || cell.verify.columns.length === 0)) {
-              errors.push({ level: 0, detail: `鎸夐挳鈥�${cell.label}鈥濅腑瀵煎嚭鍒楁湭璁剧疆锛乣})
-            }
+
+            checkBtn(cell)
 
             if (doubleClick === cell.uuid) {
               doubleClick = ''
diff --git a/src/utils/utils-datamanage.js b/src/utils/utils-datamanage.js
index 3bac86d..4544fe1 100644
--- a/src/utils/utils-datamanage.js
+++ b/src/utils/utils-datamanage.js
@@ -212,7 +212,14 @@
     }
 
     if (_customScript) {
-      if (LText) {
+      if (DateCount) {
+        DateCount = `${DateCount}
+          ${_tailScript}
+          aaa:
+          if @ErrorCode!=''
+            insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
+        `
+      } else if (LText) {
         LText = `${LText}
           ${_tailScript}
           aaa:
@@ -227,6 +234,17 @@
             insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
         `
       }
+    } else if (_tailScript && DateCount) {
+      LText = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
+        Select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
+        ${LText}
+      `
+      DateCount = `${DateCount}
+        ${_tailScript}
+        aaa:
+        if @ErrorCode!=''
+          insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,'${sessionStorage.getItem('UserID') || ''}' 
+      `
     } else if (_tailScript) {
       LText = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000),@UserName nvarchar(50),@FullName nvarchar(50),@RoleID nvarchar(512),@mk_departmentcode nvarchar(512),@mk_organization nvarchar(512),@mk_user_type nvarchar(20),@mk_nation nvarchar(50),@mk_province nvarchar(50),@mk_city nvarchar(50),@mk_district nvarchar(50),@mk_address nvarchar(100)
         Select @ErrorCode='',@retmsg ='',@UserName='${userName}', @FullName='${fullName}', @RoleID='${RoleID}', @mk_departmentcode='${departmentcode}', @mk_organization='${organization}', @mk_user_type='${mk_user_type}', @mk_nation='${nation}', @mk_province='${province}', @mk_city='${city}', @mk_district='${district}', @mk_address='${address}'
@@ -247,6 +265,7 @@
     if (window.GLOB.debugger === true) {
       _customScript && console.info(`${setting.$name ? `/*${setting.$name} 鑷畾涔夎剼鏈�*/\n` : ''}${LText ? '' : '/*涓嶆墽琛岄粯璁ql*/\n'}${_customScript}`)
       LText && console.info(`${setting.$name ? `/*${setting.$name} 鏁版嵁婧�*/\n` : ''}` + LText.replace(/\n\s{8}/ig, '\n'))
+      DateCount && console.info(`${setting.$name ? `/*${setting.$name} 鎬绘暟鏌ヨ*/\n` : ''}` + DateCount.replace(/\n\s{8}/ig, '\n'))
     }
 
     if (setting.$name) {
diff --git a/src/utils/utils.js b/src/utils/utils.js
index e874151..7da4357 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -1,3 +1,4 @@
+import React from 'react'
 import moment from 'moment'
 import md5 from 'md5'
 
@@ -2117,6 +2118,7 @@
     let status = 0
     let statusName = ''
     let detailId = ''
+    let error = ''
 
     if (verify.flowType === 'start') {
       target = flow.cells.filter(cell => cell.mknode === 'start')[0]
@@ -2125,17 +2127,112 @@
         detailId = target.id
         status = target.mkdata.status
         statusName = target.mkdata.statusName
+      } else {
+        error = '宸ヤ綔娴佹棤寮�濮嬭妭鐐�'
       }
     } else if (_data.works_flow_param) {
-      node = JSON.parse(window.decodeURIComponent(window.atob(_data.works_flow_param)))
+      try {
+        node = JSON.parse(window.decodeURIComponent(window.atob(_data.works_flow_param)))
+      } catch (e) {
+        node = null
+      }
 
       if (node) {
         let lines = flow.cells.filter(cell => cell.shape === 'edge' && cell.source.cell === node.id)
         if (verify.flowType === 'reject') {
           line = lines.filter(cell => cell.mkdata.flowType === 'reject' || cell.mknode === 'startEdge')[0]
         } else {
-          line = lines.filter(cell => cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge')[0]
+          let endEdge = null
+          lines = lines.filter(cell => {
+            if (cell.mknode === 'endEdge') {
+              endEdge = cell
+              return false
+            }
+
+            return cell.mkdata.flowType !== 'reject' && cell.mknode !== 'startEdge'
+          })
+
+          if (lines.length === 0) {
+            if (!endEdge) {
+              error = '鏃犲彲鎵ц鐨勬祦绋嬪垎鏀�'
+            } else {
+              line = endEdge
+            }
+          } else {
+            let branchKey = verify.flowBranch ? verify.flowBranch.toLowerCase() : ''
+  
+            if (!branchKey) {
+              lines.forEach(line => {
+                if (line.mkdata.execCondition === 'open') {
+                  error = '鎸夐挳鏈缃祦绋嬫帶鍒跺瓧娈点��'
+                }
+              })
+              if (!error) {
+                line = lines[0]
+              }
+            } else if (!_data.hasOwnProperty(branchKey)) {
+              error = '琛屼俊鎭腑鏃犳祦绋嬫帶鍒跺瓧娈点��'
+            } else {
+              if (endEdge) {
+                line = endEdge
+              }
+
+              let equalLine = null
+              let gtOrLtLine = []
+              let unEqualLine = null
+              let branchVal = _data[branchKey]
+
+              if (branchVal && typeof(branchVal) === 'string' && !isNaN(branchVal)) {
+                branchVal = +branchVal
+              }
+
+              lines.forEach(item => {
+                if (item.mkdata.execCondition !== 'open') {
+                  line = item
+                } else {
+                  if (item.mkdata.match === '=') {
+                    if (item.mkdata.matchVal === branchVal + '') {
+                      equalLine = item
+                    }
+                  } else if (item.mkdata.match === '!=') {
+                    if (item.mkdata.matchVal !== branchVal + '') {
+                      unEqualLine = item
+                    }
+                  } else {
+                    if (item.mkdata.match === '<') {
+                      if (item.mkdata.matchVal < branchVal) {
+                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                      }
+                    } else if (item.mkdata.match === '>') {
+                      if (item.mkdata.matchVal > branchVal) {
+                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                      }
+                    } else if (item.mkdata.match === '<=') {
+                      if (item.mkdata.matchVal <= branchVal) {
+                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                      }
+                    } else if (item.mkdata.match === '>=') {
+                      if (item.mkdata.matchVal >= branchVal) {
+                        gtOrLtLine.push({...item, dist: Math.abs(item.mkdata.matchVal - branchVal)})
+                      }
+                    }
+                  }
+                }
+              })
+
+              if (equalLine) {
+                line = equalLine
+              } else if (gtOrLtLine.length > 0) {
+                gtOrLtLine.sort((a, b) => a.dist - b.dist)
+                line = gtOrLtLine[0]
+              } else if (unEqualLine) {
+                line = unEqualLine
+              }
+            }
+          }
         }
+      } else {
+        error = '琛屼俊鎭腑宸ヤ綔娴佸弬鏁版棤娉曡В鏋�'
       }
       
       if (line) {
@@ -2143,7 +2240,11 @@
         status = line.mkdata.status
         statusName = line.mkdata.statusName
         target = flow.cells.filter(cell => cell.id === line.target.cell)[0]
+      } else if (!error) {
+        error = '宸ヤ綔娴佷腑鏃犲搴旀祦绋�'
       }
+    } else {
+      error = '琛屼俊鎭腑鏃犲伐浣滄祦鍙傛暟'
     }
 
     if (verify.flowSql === 'true' && target) {
@@ -2184,20 +2285,12 @@
       `
       }
     } else if (verify.flowSql === 'true') {
-      target = flow.cells.filter(cell => cell.mknode === 'start')[0]
-
-      if (target) {
-        detailId = target.id
-      }
-
       status = 0
       statusName = '寮傚父'
+
       _sql += `
       /* 宸ヤ綔娴佸紓甯竤ql */
-      update s_my_works_flow set status=@status@,statusname=@statusname@,works_flow_param=@works_flow_param@,works_flow_detail_id=@works_flow_detail_id@,modifydate=getdate(),modifyuserid=@userid@,modifyuser=@username,modifystaff=@fullname
-      where works_flow_id=@ID@ and works_flow_code=@works_flow_code@ and deleted=0
-      insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,upid)
-      select @ID@,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@time_id@
+      select @ErrorCode='E',@retmsg='${error || '宸ヤ綔娴佹墽琛屽紓甯�'}' goto aaa
       `
     }
 
@@ -2302,10 +2395,7 @@
  * @description 鑾峰彇鏍囪淇℃伅
  */
 export function getMark (marks, record, style = {}) {
-  let icon = null
-  let innerStyle = null
-  let position = null
-  let signType = ''
+  let res = {}
   style = JSON.parse(JSON.stringify(style))
 
   marks.some(mark => {
@@ -2342,42 +2432,45 @@
 
     if (type === 'font') {
       style.color = mark.color
-      innerStyle = {color: mark.color}
-      signType = ' sign-font'
+      res.innerStyle = {color: mark.color}
+      res.signType = ' sign-font'
     } else if (type === 'background') {
       style.backgroundColor = mark.color
       if (mark.fontColor) {
         style.color = mark.fontColor
-        innerStyle = {color: mark.fontColor}
+        res.innerStyle = {color: mark.fontColor}
       }
     } else if (type === 'underline') {
       style.textDecoration = 'underline'
       style.color = mark.color
-      innerStyle = {color: mark.color, textDecoration: 'underline'}
+      res.innerStyle = {color: mark.color, textDecoration: 'underline'}
     } else if (type === 'line-through') {
       style.textDecoration = 'line-through'
       style.color = mark.color
-      innerStyle = {color: mark.color, textDecoration: 'line-through'}
+      res.innerStyle = {color: mark.color, textDecoration: 'line-through'}
     } else if (type.indexOf('icon') > -1) {
-      icon = mark.signType[mark.signType.length - 1]
-      innerStyle = {color: mark.color}
+      res.icon = mark.signType[mark.signType.length - 1]
+      res.innerStyle = {color: mark.color}
       if (type === 'iconfront' || mark.signType[1] === 'front') {
-        position = 'front'
+        res.position = 'front'
       } else {
-        position = 'back'
+        res.position = 'back'
       }
+    } else if (type === 'indent') {
+      style.color = mark.color
+      res.space = Array(mark.signType[1] + 1).join('&nbsp;')
+    } else if (type === 'pointfront') {
+      res.position = 'front'
+      res.point = <span style={{display: 'inline-block', marginRight: '3px', width: '8px', height: '8px', borderRadius: '14px', background: mark.color, verticalAlign: 'middle'}}></span>
+    } else if (type === 'pointback') {
+      res.position = 'back'
+      res.point = <span style={{display: 'inline-block', marginLeft: '3px', width: '8px', height: '8px', borderRadius: '14px', background: mark.color, verticalAlign: 'middle'}}></span>
     }
 
     return true
   })
 
-  return {
-    style,
-    icon,
-    innerStyle,
-    position,
-    signType
-  }
+  return res
 }
 
 /**
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