From 4cc738e535d1a20701d206e12cf9de8cc5a01170 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期六, 01 六月 2024 15:24:12 +0800
Subject: [PATCH] Merge branch 'develop'

---
 src/menu/modalconfig/formfork/index.scss                                          |  177 ++
 src/templates/zshare/modalform/index.jsx                                          |   21 
 src/templates/zshare/editTable/index.jsx                                          |    4 
 src/menu/components/table/edit-table/columns/tableIn/index.jsx                    |   88 +
 src/menu/components/editor/braft-editor/options.jsx                               |   22 
 src/mob/mobshell/index.jsx                                                        |    1 
 src/utils/utils-custom.js                                                         |  196 +-
 src/mob/modulesource/option.jsx                                                   |    2 
 src/menu/components/card/balcony/options.jsx                                      |   54 
 public/options.json                                                               |    1 
 src/menu/datasource/index.jsx                                                     |    6 
 src/tabviews/custom/popview/index.jsx                                             |  324 ++--
 src/menu/components/table/edit-table/options.jsx                                  |   20 
 src/menu/stylecontroller/index.scss                                               |   28 
 src/tabviews/basetable/index.jsx                                                  |   64 
 src/templates/modalconfig/index.jsx                                               |  127 -
 src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx |   40 
 src/tabviews/custom/components/module/invoice/index.jsx                           |   20 
 src/menu/components/form/step-form/index.scss                                     |    8 
 src/mob/modalconfig/index.jsx                                                     |   98 -
 src/mob/modalconfig/index.scss                                                    |    6 
 src/assets/css/design.scss                                                        |   24 
 src/tabviews/zshare/actionList/normalbutton/index.jsx                             |   20 
 public/README.txt                                                                 |    1 
 src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx              |  138 +
 src/menu/datasource/verifycard/index.jsx                                          |   13 
 src/tabviews/custom/components/card/data-card/index.jsx                           |    9 
 src/components/normalform/modalform/mkSelect/index.jsx                            |   11 
 src/menu/components/card/data-card/options.jsx                                    |   56 
 src/menu/components/form/tab-form/index.jsx                                       |  114 -
 src/tabviews/custom/components/table/normal-table/index.jsx                       |    9 
 src/components/normalform/modalform/mkRadio/index.jsx                             |   11 
 src/templates/modalconfig/dragelement/index.scss                                  |    6 
 src/tabviews/zshare/mutilform/mkPopSelect/index.jsx                               |    8 
 src/tabviews/zshare/mutilform/index.jsx                                           |   14 
 src/tabviews/custom/components/chart/antv-X6/index.jsx                            |   10 
 src/menu/components/share/actioncomponent/actionform/index.jsx                    |    7 
 src/tabviews/custom/index.jsx                                                     |  337 ++--
 src/menu/components/card/prop-card/index.jsx                                      |    6 
 src/menu/debug/index.jsx                                                          |  136 ++
 src/mob/components/txmap/options.jsx                                              |   28 
 src/menu/components/table/edit-table/columns/index.jsx                            |    5 
 src/menu/components/form/simple-form/index.scss                                   |   12 
 src/tabviews/custom/components/table/base-table/index.jsx                         |   12 
 src/tabviews/custom/components/card/balcony/index.scss                            |    3 
 src/components/header/index.jsx                                                   |    2 
 src/menu/components/form/tab-form/index.scss                                      |    8 
 src/menu/stylecombcontroller/index.scss                                           |   28 
 src/mob/searchconfig/index.scss                                                   |    6 
 src/menu/components/form/simple-form/index.jsx                                    |  114 -
 src/tabviews/zshare/mutilform/mkSelect/index.jsx                                  |   19 
 src/mob/components/txmap/index.jsx                                                |  135 ++
 src/api/index.js                                                                  |    4 
 src/menu/components/form/step-form/options.jsx                                    |   20 
 src/menu/components/table/normal-table/columns/index.scss                         |    2 
 src/menu/components/table/edit-table/index.jsx                                    |    4 
 src/mob/mobshell/card.jsx                                                         |    3 
 src/utils/utils.js                                                                |  159 ++
 src/index.js                                                                      |   25 
 src/menu/components/card/balcony/index.jsx                                        |    6 
 src/menu/components/table/base-table/columns/index.scss                           |    2 
 src/components/normalform/modalform/index.jsx                                     |   34 
 src/menu/components/form/step-form/index.jsx                                      |  115 -
 src/mob/components/txmap/index.scss                                               |   35 
 src/templates/modalconfig/settingform/index.jsx                                   |   12 
 src/templates/zshare/formconfig.jsx                                               |   65 
 src/menu/modalconfig/formfork/index.jsx                                           |  376 +++++
 src/menu/datasource/verifycard/settingform/index.jsx                              |   12 
 src/templates/zshare/verifycard/index.jsx                                         |    6 
 src/menu/modalconfig/index.scss                                                   |   26 
 src/assets/img/map.jpg                                                            |    0 
 src/menu/modalconfig/index.jsx                                                    |  137 -
 src/tabviews/custom/components/card/balcony/index.jsx                             |   14 
 src/templates/zshare/verifycard/baseform/index.jsx                                |   50 
 src/views/login/index.jsx                                                         |   13 
 75 files changed, 2,294 insertions(+), 1,435 deletions(-)

diff --git a/public/README.txt b/public/README.txt
index fa1cceb..6cbdae7 100644
--- a/public/README.txt
+++ b/public/README.txt
@@ -14,6 +14,7 @@
 nginx             -- 鏄惁寮�鍚簡nginx鏈嶅姟锛屽�间负 true 鏃跺紑鍚紝濡傞渶浣跨敤寰俊妯℃澘娑堟伅绛夋湇鍔★紝璇峰厛璁剧疆nginx鏈嶅姟骞跺紑鍚閰嶇疆
 debugger          -- 鍊间负 true 鏃跺紑鍚皟璇曟ā寮忥紝寮�鍚悗绉诲姩绔瓙搴旂敤涓細鏈夋帶鍒跺彴
 licenseKey        -- 璁稿彲瀵嗛挜锛屽湪鍐呴儴缃戠粶涓娇鐢ㄧ郴缁熸椂锛屼細璺宠繃epc楠岃瘉
+storeKey          -- 鐢靛瓙妗f鏈湴鎺堟潈鐮侊紝浣跨敤鏈湴璁稿彲瀵嗛挜鏃舵湁鏁�
 probation         -- 璇曠敤鏈燂紙YYYY-MM-DD锛夛紝鍦ㄦ寮忕郴缁熶腑锛岃瘯鐢ㄦ湡鍐呰皟鐢ㄧ郴缁熸帴鍙g殑鑴氭湰浼氳褰曚笅鏉�
 transfer          -- 鏄惁浣跨敤杞帴鍙o紝浣跨敤杞帴鍙f椂璇疯缃负 true, 浣跨敤杞帴鍙f椂锛屽閮ㄦ帴鍙h皟鐢ㄥ墠涓嶄細鍋氱櫥褰曢獙璇�
 keepPassword      -- 璁颁綇瀵嗙爜锛岄粯璁ゅ紑鍚紝褰撳�间负 false 鏃剁鐢�
diff --git a/public/options.json b/public/options.json
index 33a2f80..ccd6826 100644
--- a/public/options.json
+++ b/public/options.json
@@ -14,6 +14,7 @@
   "nginx": "true",
   "debugger": false,
   "licenseKey": "",
+  "storeKey": "",
   "probation": "",
   "transfer": "false",
   "keepPassword": "true",
diff --git a/src/api/index.js b/src/api/index.js
index bd49113..f1c531d 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -865,8 +865,8 @@
     if (script) {
       try {
         // eslint-disable-next-line
-        let func = new Function('axios', 'Api', 'param', 'position', 'systemType', script)
-        let promise = func(axios, this, param, position, window.GLOB.systemType)
+        let func = new Function('axios', 'Api', 'param', 'position', 'systemType', 'notification', script)
+        let promise = func(axios, this, param, position, window.GLOB.systemType, notification)
 
         if (promise instanceof Promise) {
           return promise
diff --git a/src/assets/css/design.scss b/src/assets/css/design.scss
index e7a8ac6..c252031 100644
--- a/src/assets/css/design.scss
+++ b/src/assets/css/design.scss
@@ -110,3 +110,27 @@
   }
 }
 
+// 琛ㄥ崟宸ュ叿
+.mk-form-tool {
+  float: right;
+  padding-right: 15px;
+  .anticon {
+    margin-right: 15px;
+    font-size: 16px;
+    cursor: pointer!important;
+    position: relative;
+    top: 2px;
+  }
+  .anticon-copy {
+    color: #26C281;
+  }
+  .anticon-swap {
+    color: #1890ff;
+  }
+  .anticon-fork {
+    color: purple;
+  }
+  .anticon-delete {
+    color: #f5222d;
+  }
+}
diff --git a/src/assets/img/map.jpg b/src/assets/img/map.jpg
new file mode 100644
index 0000000..5dd38ff
--- /dev/null
+++ b/src/assets/img/map.jpg
Binary files differ
diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index 5697adb..1a8b396 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -578,6 +578,8 @@
           } else {
             Api.updateAppVersion()
             Api.delCacheConfig('all')
+            localStorage.removeItem(window.location.href.split('#')[0] + 'AuthCode')
+
             setTimeout(() => {
               notification.success({
                 top: 92,
diff --git a/src/components/normalform/modalform/index.jsx b/src/components/normalform/modalform/index.jsx
index 8a7599f..c685080 100644
--- a/src/components/normalform/modalform/index.jsx
+++ b/src/components/normalform/modalform/index.jsx
@@ -7,7 +7,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import MKEInput from './mkInput'
 import MKNumberInput from './mkNumberInput'
-import MKEmitter from '@/utils/events.js'
 import MKSelect from './mkSelect'
 import './index.scss'
 
@@ -155,7 +154,7 @@
       if (item.linkField) {
         let supInitVal = fieldMap.get(item.linkField).initval || ''
         
-        item.options = item.oriOptions.filter(option => option.ParentID === supInitVal)
+        item.options = item.oriOptions.filter(option => option.ParentID === supInitVal || option.ParentID === '')
       }
 
       return item
@@ -243,30 +242,27 @@
           if (item && item.linkField) {
             let supInitVal = this.record[item.linkField] || ''
             
-            item.options = item.oriOptions.filter(option => option.ParentID === supInitVal)
+            item.options = item.oriOptions.filter(option => option.ParentID === supInitVal || option.ParentID === '')
           }
 
           return item || cell
         })
       })
     } else if (item.reset_source) {
-      let map = new Map()
-      this.state.formlist.forEach(cell => {
-        if (!cell.field) return
-        map.set(cell.field, cell)
-      })
-
-      item.callback(map, this.record, MKEmitter)
-
-      this.setState({
-        formlist: this.state.formlist.map(cell => {
-          if (!cell.field) return cell
-
-          let item = map.get(cell.field)
-
-          return item || cell
+      let reOptions = item.callback(this.record)
+      
+      if (reOptions) {
+        this.setState({
+          formlist: this.state.formlist.map(cell => {
+            if (!cell.field || !reOptions[cell.field]) return cell
+  
+            cell.options = reOptions[cell.field]
+            cell.timestamp = new Date().getTime()
+            
+            return cell
+          })
         })
-      })
+      }
     }
   }
 
diff --git a/src/components/normalform/modalform/mkRadio/index.jsx b/src/components/normalform/modalform/mkRadio/index.jsx
index ddebf3e..818824f 100644
--- a/src/components/normalform/modalform/mkRadio/index.jsx
+++ b/src/components/normalform/modalform/mkRadio/index.jsx
@@ -22,6 +22,15 @@
     MKEmitter.addListener('mkFC', this.mkFormControl)
   }
 
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (nextProps.config.timestamp && nextProps.config.timestamp !== this.state.config.timestamp) {
+      this.setState({
+        config: fromJS(nextProps.config).toJS(),
+        options: fromJS(nextProps.config.options).toJS(),
+      })
+    }
+  }
+
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
   }
@@ -48,7 +57,7 @@
 
     if (field !== config.field) return
 
-    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId) : []
+    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId || option.ParentID === '') : []
     let val = options[0] ? options[0].value : ''
 
     this.setState({
diff --git a/src/components/normalform/modalform/mkSelect/index.jsx b/src/components/normalform/modalform/mkSelect/index.jsx
index 39b5546..abbd6ac 100644
--- a/src/components/normalform/modalform/mkSelect/index.jsx
+++ b/src/components/normalform/modalform/mkSelect/index.jsx
@@ -31,6 +31,15 @@
     MKEmitter.addListener('mkFC', this.mkFormControl)
   }
 
+  UNSAFE_componentWillReceiveProps(nextProps) {
+    if (nextProps.config.timestamp && nextProps.config.timestamp !== this.state.config.timestamp) {
+      this.setState({
+        config: fromJS(nextProps.config).toJS(),
+        options: fromJS(nextProps.config.options).toJS(),
+      })
+    }
+  }
+
   shouldComponentUpdate (nextProps, nextState) {
     return !is(fromJS(this.state), fromJS(nextState))
   }
@@ -57,7 +66,7 @@
 
     const { config } = this.state
 
-    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId) : []
+    let options = config.oriOptions ? config.oriOptions.filter(option => option.ParentID === parentId || option.ParentID === '') : []
     let val = options[0] ? options[0].value : ''
 
     this.setState({
diff --git a/src/index.js b/src/index.js
index 2b532b4..2fbab2f 100644
--- a/src/index.js
+++ b/src/index.js
@@ -254,6 +254,31 @@
     let lang = localStorage.getItem(_href + 'lang') || (config.defaultLang !== 'en-US' ? 'zh-CN' : 'en-US')
     sessionStorage.setItem('lang', lang)
 
+    if (localStorage.getItem(_href + 'files') === md5(_href + 'files')) {
+      let d = localStorage.getItem(_href + 'filesDate')
+
+      GLOB.storeFiles = true
+      GLOB.storeDate = Math.ceil((new Date(d).getTime() - new Date().getTime()) / 86400000)
+    } else if (GLOB.licenseKey && config.storeKey && config.storeKey.length === 16) {
+      let trans = {A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9}
+      let d = config.storeKey.slice(0, 8)
+
+      d = d.split('').map(k => trans[k]).join('')
+
+      let key = config.storeKey.slice(8)
+      let _key = GLOB.appId + GLOB.appkey + 'e_files_key' + d
+      _key = md5(_key.toLowerCase())
+      _key = _key.toUpperCase()
+      _key = _key.slice(-8)
+
+      if (key === _key) {
+        GLOB.storeFiles = true
+        
+        d = d.slice(0, 4) + '-' + d.slice(4, 6) + '-' + d.slice(6)
+        GLOB.storeDate = Math.ceil((new Date(d).getTime() - new Date().getTime()) / 86400000)
+      }
+    }
+
     GLOB.mkActions = {}  // 鎸夐挳鏉冮檺闆�
 
     Object.defineProperty(GLOB, 'appId', {
diff --git a/src/menu/components/card/balcony/index.jsx b/src/menu/components/card/balcony/index.jsx
index 516c514..e11f323 100644
--- a/src/menu/components/card/balcony/index.jsx
+++ b/src/menu/components/card/balcony/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent, getInterfaces } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from './options'
@@ -243,9 +243,9 @@
     let _card = {...this.state.card, wrap: res}
 
     if (res.datatype === 'public') {
-      let interfaces = window.GLOB.customMenu.interfaces || []
+      let interfaces = getInterfaces()
 
-      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
+      let d = interfaces.filter(m => m.value === res.publicId)[0]
 
       if (d) {
         _card.columns = fromJS(d.columns).toJS()
diff --git a/src/menu/components/card/balcony/options.jsx b/src/menu/components/card/balcony/options.jsx
index c73bf93..3361862 100644
--- a/src/menu/components/card/balcony/options.jsx
+++ b/src/menu/components/card/balcony/options.jsx
@@ -1,5 +1,5 @@
 import React from 'react'
-import MenuUtils from '@/utils/utils-custom.js'
+import MenuUtils, { getLinkModules, getInterfaces } from '@/utils/utils-custom.js'
 
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
@@ -9,22 +9,12 @@
   let isprint = sessionStorage.getItem('MenuType') === 'billPrint'
   let ispop = sessionStorage.getItem('editMenuType') === 'popview'
 
-  let modules = MenuUtils.getLinkModules(menu.components) || []
+  let modules = getLinkModules(menu.components) || []
   let supmodules = MenuUtils.getSupModules(menu.components, '', menu.interfaces)
   let roleList = sessionStorage.getItem('sysRoles')
   let appType = sessionStorage.getItem('appType')
 
-  let interfaces = []
-  if (menu.interfaces) {
-    menu.interfaces.forEach(item => {
-      if (item.status === 'true') {
-        interfaces.push({
-          value: item.uuid,
-          label: item.name
-        })
-      }
-    })
-  }
+  let interfaces = getInterfaces()
 
   if (roleList) {
     try {
@@ -61,7 +51,7 @@
       field: 'datatype',
       label: '鏁版嵁鏉ユ簮',
       initval: wrap.datatype || 'static',
-      tooltip: '閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��',
+      tooltip: '閫夋嫨闈欐�佹椂锛屾棤闇�閰嶇疆鏁版嵁婧愶紝鍙睍绀轰笂绾х粍浠舵垨url鍙傛暟瀛楁銆�',
       required: false,
       options: [
         {value: 'dynamic', label: '鍔ㄦ��'},
@@ -82,23 +72,15 @@
       required: true,
       options: interfaces,
       reset_source: true,
-      callback: (map, record) => {
+      callback: (record) => {
         if (!record.publicId) return
 
-        let interfaces = window.GLOB.customMenu.interfaces || []
-
-        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+        let d = interfaces.filter(m => m.value === record.publicId)[0]
 
         if (!d || !d.columns) return
 
-        let columns = JSON.parse(JSON.stringify(d.columns))
-
-        let _bgField = map.get('bgField')
-
-        if (_bgField && !_bgField.forbid) {
-          _bgField.options = columns
-          _bgField.oriOptions = columns
-          map.set('bgField', _bgField)
+        return {
+          bgField: d.columns
         }
       }
     },
@@ -108,15 +90,13 @@
       label: '鍙楁帶绫诲瀷',
       initval: wrap.linkType || 'static',
       tooltip: <div>
-        <div>缁勪欢涓庡叾浠栫粍浠朵箣闂寸殑鎺у埗绫诲瀷: </div>
-        <div>1銆佺嫭绔嬭〃绀轰笌鍏朵粬缁勪欢娌℃湁鍏宠仈銆�</div>
-        <div>2銆佸悓姝ョ被鍨嬩腑鍏紡銆佹寜閽互鍙婂叏閫夊厓绱犳瘮杈冪壒娈婏紝鎿嶄綔鏁版嵁涓哄叾鍚屾缁勪欢鐨勬暟鎹��</div>
-        <div>3銆佷笂绾х被鍨嬮渶娣诲姞褰撳墠缁勪欢鐨勪笂绾х粍浠讹紝骞跺彲璁剧疆褰撳墠缁勪欢涓哄缁堟樉绀猴紝杩樻槸鍙湁鍦ㄤ笂绾х粍浠堕�夎鍚庢墠鏄剧ず銆�</div>
+        <div>鍚屾绫诲瀷锛氭绫诲瀷鏃跺叕寮忋�佹寜閽互鍙婂叏閫夊厓绱犳瘮杈冪壒娈婏紝鎿嶄綔鏁版嵁涓哄叾鍚屾缁勪欢閫変腑鐨勬暟鎹��</div>
+        <div>涓婄骇绫诲瀷锛氬彲璁剧疆褰撳墠缁勪欢鐨勬樉绀烘潯浠讹紙濮嬬粓鏄剧ず鎴栦笂绾ч�夎鏃舵樉绀猴級锛屼笌闈欐�佹暟鎹簮閰嶅悎涔熷彲鐢ㄤ簬灞曠ず涓婄骇缁勪欢閫変腑鐨勪俊鎭��</div>
       </div>,
       toolWidth: 400,
       required: false,
       options: [
-        {value: 'static', label: '鐙珛'},
+        {value: 'static', label: '鏃�'},
         {value: 'sync', label: '鍚屾'},
         {value: 'sup', label: '涓婄骇'},
       ],
@@ -133,7 +113,6 @@
       field: 'supModule',
       label: '涓婄骇缁勪欢',
       initval: wrap.supModule || [],
-      // tooltip: '褰撲笂绾х粍浠朵笉瀛樺湪鎴栨病鏈夋潈闄愭椂锛屽綋鍓嶇粍浠朵笉鏄剧ず銆�',
       required: true,
       options: supmodules,
       forbid: isprint
@@ -149,6 +128,16 @@
         {value: 'hidden', label: '閫夎'},
         {value: 'show', label: '濮嬬粓'},
       ],
+      forbid: isprint
+    },
+    {
+      type: 'cascader',
+      field: 'syncModule',
+      label: '鍚屾缁勪欢',
+      initval: wrap.syncModule || '',
+      tooltip: '褰撳悓姝ョ粍浠朵笉瀛樺湪鎴栨病鏈夋潈闄愭椂锛屽綋鍓嶇粍浠朵笉鏄剧ず銆�',
+      required: true,
+      options: modules,
       forbid: isprint
     },
     {
@@ -193,6 +182,7 @@
       label: '鑳屾櫙鍥�',
       initval: wrap.bgField || '',
       tooltip: '鍔ㄦ�佽儗鏅紝鑳屾櫙鍥剧墖鐢卞瓧娈靛�兼帶鍒躲�傝娉ㄦ剰璋冩暣鑳屾櫙鏍峰紡銆�',
+      timestamp: new Date().getTime(),
       required: false,
       options: columns
     },
diff --git a/src/menu/components/card/data-card/options.jsx b/src/menu/components/card/data-card/options.jsx
index 91f71f7..29de319 100644
--- a/src/menu/components/card/data-card/options.jsx
+++ b/src/menu/components/card/data-card/options.jsx
@@ -1,4 +1,4 @@
-import MenuUtils from '@/utils/utils-custom.js'
+import MenuUtils, { getInterfaces } from '@/utils/utils-custom.js'
 
 /**
  * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
@@ -9,16 +9,10 @@
   let ispop = sessionStorage.getItem('editMenuType') === 'popview'
   let menu = window.GLOB.customMenu
   let laypage = setting && setting.laypage !== 'false'
+
   let interfaces = []
-  if (subtype === 'propcard' && menu.interfaces) {
-    menu.interfaces.forEach(item => {
-      if (item.status === 'true') {
-        interfaces.push({
-          value: item.uuid,
-          label: item.name
-        })
-      }
-    })
+  if (subtype === 'propcard') {
+    interfaces = getInterfaces()
   }
   let modules = []
   if (subtype === 'propcard' || subtype === 'datacard') {
@@ -159,7 +153,7 @@
       field: 'datatype',
       label: '鏁版嵁鏉ユ簮',
       initval: wrap.datatype || 'dynamic',
-      tooltip: '閫夋嫨闈欐�佸�硷紝鏃犻渶閰嶇疆鏁版嵁婧愩��',
+      tooltip: '閫夋嫨闈欐�佹椂锛屾棤闇�閰嶇疆鏁版嵁婧愶紝鍙睍绀轰笂绾х粍浠舵垨url鍙傛暟瀛楁銆�',
       required: false,
       options: [
         {value: 'dynamic', label: '鍔ㄦ��', priKeyType: 'static'},
@@ -187,38 +181,17 @@
       options: interfaces,
       reset_source: true,
       forbid: subtype !== 'propcard',
-      callback: (map, record) => {
+      callback: (record) => {
         if (!record.publicId) return
         
-        let interfaces = window.GLOB.customMenu.interfaces || []
-        
-        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+        let d = interfaces.filter(m => m.value === record.publicId)[0]
         
         if (!d || !d.columns) return
-        let columns = JSON.parse(JSON.stringify(d.columns))
 
-        let _broadcast = map.get('broadcast')
-
-        if (_broadcast && !_broadcast.forbid) {
-          _broadcast.options = columns
-          _broadcast.oriOptions = columns
-          map.set('broadcast', _broadcast)
-        }
-        
-        let _jumpField = map.get('jumpField')
-
-        if (_jumpField && !_jumpField.forbid) {
-          _jumpField.options = columns
-          _jumpField.oriOptions = columns
-          map.set('jumpField', _jumpField)
-        }
-
-        let _link = map.get('link')
-
-        if (_link && !_link.forbid) {
-          _link.options = columns
-          _link.oriOptions = columns
-          map.set('link', _link)
+        return {
+          broadcast: d.columns,
+          jumpField: d.columns,
+          link: d.columns
         }
       }
     },
@@ -287,11 +260,9 @@
       required: false,
       linkField: 'datatype',
       options: [
-        {ParentID: 'static', value: 'static', label: '闈欐�佸��'},
-        {ParentID: 'dynamic', value: 'static', label: '闈欐�佸��'},
+        {ParentID: '', value: 'static', label: '闈欐�佸��'},
         {ParentID: 'dynamic', value: 'dynamic', label: '鍔ㄦ�佸��'},
         {ParentID: 'dynamic', value: 'joint', label: '鎷兼帴鍊�'},
-        {ParentID: 'public', value: 'static', label: '闈欐�佸��'},
         {ParentID: 'public', value: 'dynamic', label: '鍔ㄦ�佸��'},
         {ParentID: 'public', value: 'joint', label: '鎷兼帴鍊�'},
       ],
@@ -427,6 +398,7 @@
       label: '璇煶鎾姤',
       initval: wrap.broadcast || '',
       tooltip: '璇煶鎾姤鍦ㄧЩ鍔ㄧ鏈夋晥銆傛敞锛氬湪H5涓浣跨敤闊抽閾炬帴锛屾坊鍔犲畾鏃跺櫒鏃讹紝鍙惊鐜挱鎶�',
+      timestamp: new Date().getTime(),
       required: false,
       options: columns,
       forbid: !columns || appType !== 'mob' || subtype !== 'propcard'
@@ -525,6 +497,7 @@
       label: '鎺у埗瀛楁',
       initval: wrap.jumpField || '',
       tooltip: '褰撳瓧娈靛�间负true鏃惰Е鍙戣烦杞��',
+      timestamp: new Date().getTime(),
       required: true,
       options: columns,
       forbid: subtype !== 'propcard' || appType !== 'mob'
@@ -544,6 +517,7 @@
       label: '閾炬帴瀛楁',
       initval: wrap.link || '',
       tooltip: '璺宠浆閾炬帴涓烘煡璇㈡暟鎹殑杩斿洖鍊笺��',
+      timestamp: new Date().getTime(),
       required: true,
       options: columns,
       forbid: subtype !== 'propcard' || appType !== 'mob'
diff --git a/src/menu/components/card/prop-card/index.jsx b/src/menu/components/card/prop-card/index.jsx
index c0b2914..9f17c5f 100644
--- a/src/menu/components/card/prop-card/index.jsx
+++ b/src/menu/components/card/prop-card/index.jsx
@@ -6,7 +6,7 @@
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
-import { resetStyle, getTables, checkComponent } from '@/utils/utils-custom.js'
+import { resetStyle, getTables, checkComponent, getInterfaces } from '@/utils/utils-custom.js'
 import MKEmitter from '@/utils/events.js'
 import Utils from '@/utils/utils.js'
 import getWrapForm from '../data-card/options'
@@ -331,9 +331,9 @@
         _card.setting.supModule = ''
       }
     } else if (res.datatype === 'public') {
-      let interfaces = window.GLOB.customMenu.interfaces || []
+      let interfaces = getInterfaces()
 
-      let d = interfaces.filter(m => m.uuid === res.publicId && m.status === 'true')[0]
+      let d = interfaces.filter(m => m.value === res.publicId)[0]
 
       if (d) {
         _card.columns = fromJS(d.columns).toJS()
diff --git a/src/menu/components/editor/braft-editor/options.jsx b/src/menu/components/editor/braft-editor/options.jsx
index 922cc66..e0bb4a2 100644
--- a/src/menu/components/editor/braft-editor/options.jsx
+++ b/src/menu/components/editor/braft-editor/options.jsx
@@ -7,14 +7,15 @@
   let isprint = sessionStorage.getItem('MenuType') === 'billPrint'
   let ispop = sessionStorage.getItem('editMenuType') === 'popview'
   let menu = window.GLOB.customMenu
-
   let interfaces = []
+
   if (menu.interfaces) {
     menu.interfaces.forEach(item => {
       if (item.status === 'true') {
         interfaces.push({
           value: item.uuid,
-          label: item.name
+          label: item.name,
+          columns: JSON.parse(JSON.stringify(item.columns))
         })
       }
     })
@@ -84,23 +85,15 @@
       required: true,
       options: interfaces,
       reset_source: true,
-      callback: (map, record) => {
+      callback: (record) => {
         if (!record.publicId) return
 
-        let interfaces = window.GLOB.customMenu.interfaces || []
-
-        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+        let d = interfaces.filter(m => m.value === record.publicId)[0]
 
         if (!d || !d.columns) return
 
-        let columns = JSON.parse(JSON.stringify(d.columns))
-
-        let _field = map.get('field')
-
-        if (_field) {
-          _field.options = columns
-          _field.oriOptions = columns
-          map.set('field', _field)
+        return {
+          field: d.columns
         }
       }
     },
@@ -109,6 +102,7 @@
       field: 'field',
       label: '鏂囨湰瀛楁',
       initval: wrap.field || '',
+      timestamp: new Date().getTime(),
       required: false,
       options: columns
     },
diff --git a/src/menu/components/form/simple-form/index.jsx b/src/menu/components/form/simple-form/index.jsx
index 2d1855a..07e1e2f 100644
--- a/src/menu/components/form/simple-form/index.jsx
+++ b/src/menu/components/form/simple-form/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Modal, Button, Switch, message } from 'antd'
-import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, SwapOutlined, FontColorsOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -19,6 +19,7 @@
 const CardComponent = asyncComponent(() => import('@/templates/modalconfig/dragelement'))
 const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement'))
 const FormAction = asyncComponent(() => import('../formaction'))
+const FormFork = asyncComponent(() => import('@/menu/modalconfig/formfork'))
 const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteForms = asyncIconComponent(() => import('@/menu/components/share/pasteforms'))
@@ -41,8 +42,7 @@
     visible: false,
     editform: null,
     formlist: null,
-    sqlVerifing: false,
-    standardform: null
+    sqlVerifing: false
   }
 
   UNSAFE_componentWillMount () {
@@ -346,90 +346,14 @@
    * @description 琛ㄥ崟缂栬緫
    */
   handleForm = (_item) => {
-    const { card, appType } = this.state
+    const { card } = this.state
+
     let _form = fromJS(_item).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    card.subcards[0].fields.forEach((item, i) => {
-      if (_form.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || _form.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (['switch', 'check', 'popSelect'].includes(item.type)) {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      
-      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-
-    if (index !== null) {
-      if (index === 0) {
-        standardform = card.subcards[0].fields[index + 1] || null
-      } else {
-        standardform = card.subcards[0].fields[index - 1] || null
-      }
-    }
-
-    let _fields = _linkableFields.map(cell => cell.field)
-    card.columns.forEach(col => {
-      if (col.field && !_fields.includes(col.field)) {
-        _linkableFields.push({
-          field: col.field,
-          label: col.label + '-鏄剧ず鍒�'
-        })
-      }
-    })
-
-    if (_form.linkSubField && _form.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      _form.linkSubField = _form.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (appType !== 'mob' && !_form.span && standardform && standardform.span) {
-      _form.span = standardform.span
-      _form.labelwidth = standardform.labelwidth
-    }
 
     this.setState({
-      standardform,
       visible: true,
       editform: _form,
-      formlist: getModalForm(_form, _inputfields, _tabfields, _linkableFields, _linksupFields, card.columns)
+      formlist: getModalForm(_form, card.subcards[0].fields, card.columns)
     })
   }
 
@@ -442,7 +366,7 @@
   handleSubmit = () => {
     let _config = fromJS(this.state.card).toJS()
 
-    this.formRef.handleConfirm(_config.subcards[0].fields).then(res => {
+    this.formRef.handleConfirm().then(res => {
       _config.subcards[0].fields = _config.subcards[0].fields.map(item => {
         delete item.focus
 
@@ -626,12 +550,22 @@
         <div className={`form-area mk-${card.wrap.formStyle || ''}`}>
           <PlusOutlined className="plus" title="娣诲姞琛ㄥ崟" onClick={this.addForm}/>
           <FieldsComponent config={card.subcards[0]} type="form" plusFields={this.plusFields} />
-          <span style={{color: 'red', marginLeft: '30px', cursor: 'pointer'}} onClick={this.clearGroup}>娓呯┖</span>
-          <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button> : null}
+          <div className="mk-form-tool">
+            <DeleteOutlined title="娓呯┖" onClick={this.clearGroup} />
+            {appType !== 'mob' ? <Popover title="鍒囨崲甯冨眬" overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+              <>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(1)}>1鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(2)}>2鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(3)}>3鍒�</Button>
+                <Button onClick={() => this.changecols(4)}>4鍒�</Button>
+              </>
+            } trigger="hover">
+              <SwapOutlined />
+            </Popover> : null}
+            <FormFork forms={card.subcards[0].fields}/>
+            {/* <CopyOutlined title="澶嶅埗" onClick={this.triggerCopy} /> */}
+            <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
+          </div>
           <div style={{clear: 'both'}}></div>
           {appType !== 'mob' ? <CardComponent
             list={card.subcards[0].fields}
@@ -687,7 +621,7 @@
             card={this.state.editform}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={card.subcards[0].fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/menu/components/form/simple-form/index.scss b/src/menu/components/form/simple-form/index.scss
index 5911202..2615482 100644
--- a/src/menu/components/form/simple-form/index.scss
+++ b/src/menu/components/form/simple-form/index.scss
@@ -34,14 +34,6 @@
       cursor: pointer;
       padding: 4px 10px;
     }
-    >button {
-      float: right;
-      margin-right: 10px;
-    }
-    >.mk-cols-change {
-      height: 24px;
-      padding: 0 10px;
-    }
     >.quickly-add {
       display: inline-block;
       margin-left: 10px;
@@ -78,12 +70,12 @@
   //   }
   // }
 }
-.menu-normal-form-edit-box::after {
+.menu-simple-form-edit-box::after {
   display: block;
   content: ' ';
   clear: both;
 }
-.menu-normal-form-edit-box:hover {
+.menu-simple-form-edit-box:hover {
   z-index: 1;
   box-shadow: 0px 0px 4px #1890ff;
 }
diff --git a/src/menu/components/form/step-form/index.jsx b/src/menu/components/form/step-form/index.jsx
index 8704f5e..4395d59 100644
--- a/src/menu/components/form/step-form/index.jsx
+++ b/src/menu/components/form/step-form/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Modal, Button, Switch, notification, message } from 'antd'
-import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, SwapOutlined, FontColorsOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -20,6 +20,7 @@
 const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement'))
 const FormTitle = asyncComponent(() => import('../dragtitle'))
 const FormAction = asyncComponent(() => import('../formaction'))
+const FormFork = asyncComponent(() => import('@/menu/modalconfig/formfork'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
@@ -42,8 +43,7 @@
     visible: false,
     editform: null,
     formlist: null,
-    sqlVerifing: false,
-    standardform: null
+    sqlVerifing: false
   }
 
   UNSAFE_componentWillMount () {
@@ -447,91 +447,14 @@
    * @description 琛ㄥ崟缂栬緫
    */
   handleForm = (_item) => {
-    const { card, group, appType } = this.state
+    const { card, group } = this.state
+
     let _form = fromJS(_item).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    group.fields.forEach((item, i) => {
-      if (_form.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || _form.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (['switch', 'check', 'popSelect'].includes(item.type)) {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      
-      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-
-    if (index !== null) {
-      if (index === 0) {
-        standardform = group.fields[index + 1] || null
-      } else {
-        standardform = group.fields[index - 1] || null
-      }
-    }
-
-    let _fields = _linkableFields.map(cell => cell.field)
-    card.columns.forEach(col => {
-      if (col.field && !_fields.includes(col.field)) {
-        _linkableFields.push({
-          field: col.field,
-          label: col.label + '-鏄剧ず鍒�'
-        })
-      }
-    })
-
-    if (_form.linkSubField && _form.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      _form.linkSubField = _form.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (appType !== 'mob' && !_form.span && standardform && standardform.span) {
-      _form.span = standardform.span
-      _form.labelwidth = standardform.labelwidth
-    }
 
     this.setState({
-      standardform,
       visible: true,
       editform: _form,
-      formlist: getModalForm(_form, _inputfields, _tabfields, _linkableFields, _linksupFields, card.columns)
+      formlist: getModalForm(_form, group.fields, card.columns)
     })
   }
 
@@ -544,7 +467,7 @@
   handleSubmit = () => {
     let _config = fromJS(this.state.group).toJS()
 
-    this.formRef.handleConfirm(_config.fields).then(res => {
+    this.formRef.handleConfirm().then(res => {
       _config.fields = _config.fields.map(item => {
         delete item.focus
 
@@ -742,12 +665,22 @@
         {group ? <div className={`form-area mk-${card.wrap.formStyle || ''}`}>
           <PlusOutlined className="plus" title="娣诲姞琛ㄥ崟" onClick={this.addForm}/>
           <FieldsComponent config={group} type="form" plusFields={this.plusFields} />
-          <span style={{color: 'red', marginLeft: '30px', cursor: 'pointer'}} onClick={this.clearGroup}>娓呯┖</span>
-          <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button> : null}
+          <div className="mk-form-tool">
+            <DeleteOutlined title="娓呯┖" onClick={this.clearGroup} />
+            {appType !== 'mob' ? <Popover title="鍒囨崲甯冨眬" overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+              <>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(1)}>1鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(2)}>2鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(3)}>3鍒�</Button>
+                <Button onClick={() => this.changecols(4)}>4鍒�</Button>
+              </>
+            } trigger="hover">
+              <SwapOutlined />
+            </Popover> : null}
+            <FormFork forms={group.fields}/>
+            {/* <CopyOutlined title="澶嶅埗" onClick={this.triggerCopy} /> */}
+            <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
+          </div>
           <div style={{clear: 'both'}}></div>
           {appType !== 'mob' ? <CardComponent
             list={group.fields}
@@ -803,7 +736,7 @@
             card={this.state.editform}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={group.fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/menu/components/form/step-form/index.scss b/src/menu/components/form/step-form/index.scss
index 40539f2..5f2d0f2 100644
--- a/src/menu/components/form/step-form/index.scss
+++ b/src/menu/components/form/step-form/index.scss
@@ -35,14 +35,6 @@
       cursor: pointer;
       padding: 4px 10px;
     }
-    >button {
-      float: right;
-      margin-right: 10px;
-    }
-    >.mk-cols-change {
-      height: 24px;
-      padding: 0 10px;
-    }
     >.quickly-add {
       display: inline-block;
       margin-left: 10px;
diff --git a/src/menu/components/form/step-form/options.jsx b/src/menu/components/form/step-form/options.jsx
index 647d7a0..aca8cd7 100644
--- a/src/menu/components/form/step-form/options.jsx
+++ b/src/menu/components/form/step-form/options.jsx
@@ -35,7 +35,8 @@
       if (item.status === 'true') {
         interfaces.push({
           value: item.uuid,
-          label: item.name
+          label: item.name,
+          columns: JSON.parse(JSON.stringify(item.columns))
         })
       }
     })
@@ -87,23 +88,15 @@
       required: true,
       options: interfaces,
       reset_source: config.subtype !== 'tabform',
-      callback: (map, record) => {
+      callback: (record) => {
         if (!record.publicId) return
 
-        let interfaces = window.GLOB.customMenu.interfaces || []
-
-        let d = interfaces.filter(m => m.uuid === record.publicId && m.status === 'true')[0]
+        let d = interfaces.filter(m => m.value === record.publicId)[0]
 
         if (!d || !d.columns) return
 
-        let columns = JSON.parse(JSON.stringify(d.columns))
-
-        let _sCtrl = map.get('statusControl')
-
-        if (_sCtrl && !_sCtrl.forbid) {
-          _sCtrl.options = columns
-          _sCtrl.oriOptions = columns
-          map.set('statusControl', _sCtrl)
+        return {
+          statusControl: d.columns
         }
       }
     },
@@ -113,6 +106,7 @@
       label: '鐘舵�佹帶鍒�',
       initval: wrap.statusControl || '',
       tooltip: '琛ㄥ崟鍔犺浇鏃剁殑鐘舵�侊紝褰撳瓧娈靛�间笌琛ㄥ崟缁勭殑鐘舵�佸�间竴鑷存椂锛屽惎鐢ㄥ搴旂殑琛ㄥ崟缁勩��',
+      timestamp: new Date().getTime(),
       required: false,
       options: config.columns,
       forbid: config.subtype === 'tabform'
diff --git a/src/menu/components/form/tab-form/index.jsx b/src/menu/components/form/tab-form/index.jsx
index 8ee36a7..c895e37 100644
--- a/src/menu/components/form/tab-form/index.jsx
+++ b/src/menu/components/form/tab-form/index.jsx
@@ -2,7 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Popover, Modal, Button, Switch, notification, message } from 'antd'
-import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+import { PlusOutlined, SettingOutlined, EditOutlined, ToolOutlined, DeleteOutlined, SwapOutlined, FontColorsOutlined } from '@ant-design/icons'
 
 import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
@@ -20,6 +20,7 @@
 const MobCardComponent = asyncComponent(() => import('@/mob/components/formdragelement'))
 const FormTitle = asyncComponent(() => import('../dragtitle'))
 const FormAction = asyncComponent(() => import('../formaction'))
+const FormFork = asyncComponent(() => import('@/menu/modalconfig/formfork'))
 const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
 const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
@@ -42,8 +43,7 @@
     visible: false,
     editform: null,
     formlist: null,
-    sqlVerifing: false,
-    standardform: null
+    sqlVerifing: false
   }
 
   UNSAFE_componentWillMount () {
@@ -453,90 +453,14 @@
    * @description 琛ㄥ崟缂栬緫
    */
   handleForm = (_item) => {
-    const { card, group, appType } = this.state
+    const { card, group } = this.state
+
     let _form = fromJS(_item).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    group.fields.forEach((item, i) => {
-      if (_form.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || _form.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (['switch', 'check', 'popSelect'].includes(item.type)) {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      
-      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-
-    if (index !== null) {
-      if (index === 0) {
-        standardform = group.fields[index + 1] || null
-      } else {
-        standardform = group.fields[index - 1] || null
-      }
-    }
-
-    let _fields = _linkableFields.map(cell => cell.field)
-    card.columns.forEach(col => {
-      if (col.field && !_fields.includes(col.field)) {
-        _linkableFields.push({
-          field: col.field,
-          label: col.label + '-鏄剧ず鍒�'
-        })
-      }
-    })
-
-    if (_form.linkSubField && _form.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      _form.linkSubField = _form.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (appType !== 'mob' && !_form.span && standardform && standardform.span) {
-      _form.span = standardform.span
-      _form.labelwidth = standardform.labelwidth
-    }
 
     this.setState({
-      standardform,
       visible: true,
       editform: _form,
-      formlist: getModalForm(_form, _inputfields, _tabfields, _linkableFields, _linksupFields, card.columns)
+      formlist: getModalForm(_form, group.fields, card.columns)
     })
   }
 
@@ -549,7 +473,7 @@
   handleSubmit = () => {
     let _config = fromJS(this.state.group).toJS()
 
-    this.formRef.handleConfirm(_config.fields).then(res => {
+    this.formRef.handleConfirm().then(res => {
       _config.fields = _config.fields.map(item => {
         delete item.focus
 
@@ -744,12 +668,22 @@
         {group ? <div className={`form-area mk-${card.wrap.formStyle || ''}`}>
           <PlusOutlined className="plus" title="娣诲姞琛ㄥ崟" onClick={this.addForm}/>
           <FieldsComponent config={group} type="form" plusFields={this.plusFields} />
-          <span style={{color: 'red', marginLeft: '30px', cursor: 'pointer'}} onClick={this.clearGroup}>娓呯┖</span>
-          <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(1)}>1鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(2)}>2鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(3)}>3鍒�</Button> : null}
-          {appType !== 'mob' ? <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button> : null}
+          <div className="mk-form-tool">
+            <DeleteOutlined title="娓呯┖" onClick={this.clearGroup} />
+            {appType !== 'mob' ? <Popover title="鍒囨崲甯冨眬" overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+              <>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(1)}>1鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(2)}>2鍒�</Button>
+                <Button style={{marginRight: '10px'}} onClick={() => this.changecols(3)}>3鍒�</Button>
+                <Button onClick={() => this.changecols(4)}>4鍒�</Button>
+              </>
+            } trigger="hover">
+              <SwapOutlined />
+            </Popover> : null}
+            <FormFork forms={group.fields}/>
+            {/* <CopyOutlined title="澶嶅埗" onClick={this.triggerCopy} /> */}
+            <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
+          </div>
           <div style={{clear: 'both'}}></div>
           {appType !== 'mob' ? <CardComponent
             list={group.fields}
@@ -805,7 +739,7 @@
             card={this.state.editform}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={group.fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/menu/components/form/tab-form/index.scss b/src/menu/components/form/tab-form/index.scss
index ffb7696..76ad654 100644
--- a/src/menu/components/form/tab-form/index.scss
+++ b/src/menu/components/form/tab-form/index.scss
@@ -34,14 +34,6 @@
       cursor: pointer;
       padding: 4px 10px;
     }
-    >button {
-      float: right;
-      margin-right: 10px;
-    }
-    >.mk-cols-change {
-      height: 24px;
-      padding: 0 10px;
-    }
     >.quickly-add {
       display: inline-block;
       margin-left: 10px;
diff --git a/src/menu/components/share/actioncomponent/actionform/index.jsx b/src/menu/components/share/actioncomponent/actionform/index.jsx
index c00ec97..3f88b64 100644
--- a/src/menu/components/share/actioncomponent/actionform/index.jsx
+++ b/src/menu/components/share/actioncomponent/actionform/index.jsx
@@ -723,6 +723,10 @@
       } else if (value === 'custom') {
         _fieldval.Ot = 'required'
       }
+      if (_fieldval.Ot === 'required' && this.record.execError === 'never') {
+        this.record.execError = 'grid'
+        _fieldval.execError = 'grid'
+      }
 
       if (this.props.type === 'card' && _fieldval.Ot === 'required') { // 鍗$墖涓棤澶氳閫夐」
         _fieldval.Ot = 'requiredSgl'
@@ -741,6 +745,9 @@
       if (appType !== 'mob' && value === 'notRequired') {
         this.record.control = ''
         _fieldval.control = ''
+      } else if (value === 'required' && this.record.execError === 'never') {
+        this.record.execError = 'grid'
+        _fieldval.execError = 'grid'
       }
     } else if (key === 'pageTemplate') {
       if (value === 'pay') {
diff --git a/src/menu/components/table/base-table/columns/index.scss b/src/menu/components/table/base-table/columns/index.scss
index 48aae5d..f8e6c1c 100644
--- a/src/menu/components/table/base-table/columns/index.scss
+++ b/src/menu/components/table/base-table/columns/index.scss
@@ -45,7 +45,7 @@
       }
       td:not(.ant-table-selection-column) {
         position: relative;
-        padding: 12px 8px;
+        // padding: 12px 8px;
         >.profile {
           position: absolute;
           top: 2px;
diff --git a/src/menu/components/table/edit-table/columns/index.jsx b/src/menu/components/table/edit-table/columns/index.jsx
index b410cc8..120c12b 100644
--- a/src/menu/components/table/edit-table/columns/index.jsx
+++ b/src/menu/components/table/edit-table/columns/index.jsx
@@ -637,10 +637,6 @@
     })
   }
 
-  componentDidMount () {
-    MKEmitter.addListener('submitStyle', this.getStyle)
-  }
-
   /**
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
    */
@@ -648,7 +644,6 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('submitStyle', this.getStyle)
   }
 
   handlecolumns = (columns, fields, config, pId) => {
diff --git a/src/menu/components/table/edit-table/columns/tableIn/index.jsx b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
index 0b443d7..4bf55dc 100644
--- a/src/menu/components/table/edit-table/columns/tableIn/index.jsx
+++ b/src/menu/components/table/edit-table/columns/tableIn/index.jsx
@@ -104,6 +104,92 @@
             </div>
           )
       },
+      {
+        dataIndex: 'sqlRender',
+        render: (record) => {
+          let columns = this.props.config.columns
+
+          let textFields = []
+          let numberFields = []
+          let dateFields = []
+          columns.forEach((col) => {
+            if (/Nvarchar/ig.test(col.datatype)) {
+              textFields.push(col.field)
+            } else if (/Decimal|int/ig.test(col.datatype)) {
+              numberFields.push(col.field)
+            } else if (/date/ig.test(col.datatype)) {
+              dateFields.push(col.field)
+            }
+          })
+
+          let _sheet = this.state.verify.sheet
+
+          if (window.GLOB.externalDatabase !== null) {
+            _sheet = _sheet.replace(/@db@/ig, window.GLOB.externalDatabase)
+          }
+
+          let database = _sheet.match(/(.*)\.(.*)\./ig)
+          let sheet = _sheet.replace(/(.*)\.(.*)\./ig, '')
+          
+          database = database ? (database[0] || '') : ''
+
+          let _fields = record.field.split(',')
+          let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
+          _fields_ = _fields_.join(' and ')
+
+          let _where = []
+          _fields.forEach(f => {
+            if (textFields.includes(f)) {
+              _where.push(`${f}!=''`)
+            } else if (numberFields.includes(f)) {
+              _where.push(`${f}!=0`)
+            } else if (dateFields.includes(f)) {
+              _where.push(`${f}>'1949-10-01'`)
+            }
+          })
+          _where = _where.length ? `where ${_where.join(' and ')} ` : ''
+
+          if (record.verifyType === 'logic' || record.verifyType === 'logic_temp') {
+            _fields_ += ' and b.deleted=0'
+          }
+
+          let _afields = []
+          _fields = _fields.map(f => {
+            if (numberFields.includes(f)) {
+              _afields.push(`cast(a.${f} as nvarchar(50))`)
+              return `cast(${f} as nvarchar(50))`
+            } else if (dateFields.includes(f)) {
+              _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+              return `CONVERT(nvarchar(50), ${f}, 21)`
+            }
+            _afields.push(`a.${f}`)
+
+            return f
+          })
+
+          let sql = `
+          /* 閲嶅鎬ч獙璇� */
+          Set @tbid=''
+          Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${record.field} from #${sheet} ) a group by ${record.field} having sum(n)>1
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${record.errorCode}',@retmsg=@tbid+' 閲嶅'
+            goto aaa
+          end
+          
+          ${record.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
+          Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${database}${sheet} b on ${_fields_}
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${record.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
+            goto aaa
+          end` : ''}
+          `
+          return sql.split(/\n\s{10}/ig).map(n => n.replace(/^\s{2}/ig, '&nbsp;&nbsp;'))
+        }
+      }
     ],
     scriptsColumns: [
       {
@@ -611,7 +697,7 @@
             </span>
           } key="unique">
             <UniqueForm fields={fields} uniqueChange={this.uniqueChange}/>
-            <EditTable actions={['edit', 'move', 'del']} data={verify.uniques} columns={uniqueColumns} onChange={this.changeUniques}/>
+            <EditTable actions={['edit', 'move', 'del', 'sql']} data={verify.uniques} columns={uniqueColumns} onChange={this.changeUniques}/>
           </TabPane>
           <TabPane disabled={verify.intertype !== 'system'} tab={
             <span>
diff --git a/src/menu/components/table/edit-table/index.jsx b/src/menu/components/table/edit-table/index.jsx
index b6bfbee..3e92baf 100644
--- a/src/menu/components/table/edit-table/index.jsx
+++ b/src/menu/components/table/edit-table/index.jsx
@@ -284,6 +284,10 @@
     res.borderRadius = card.wrap.borderRadius || 0
     res.resetContrl = card.wrap.resetContrl || 'init'
 
+    if (res.commit === 'check' && !res.tableType) {
+      res.tableType = 'radio'
+    }
+
     let _card = {...card, wrap: res}
 
     if (res.tableType) {
diff --git a/src/menu/components/table/edit-table/options.jsx b/src/menu/components/table/edit-table/options.jsx
index f3e8d31..78c1a63 100644
--- a/src/menu/components/table/edit-table/options.jsx
+++ b/src/menu/components/table/edit-table/options.jsx
@@ -67,18 +67,13 @@
         {value: 'check', label: '鍕鹃�夐」'},
       ],
       reset_source: true,
-      callback: (map, record, MKEmitter) => {
-        let _tableType = map.get('tableType')
-
-        _tableType.options[0].disabled = record.commit === 'check'
-        _tableType.oriOptions[0].disabled = record.commit === 'check'
-
-        map.set('tableType', _tableType)
-
-        if (record.commit === 'check' && !record.tableType) {
-          setTimeout(() => {
-            MKEmitter.emit('mkFC', 'input', 'tableType', 'radio')
-          }, 50)
+      callback: (record) => {
+        return {
+          tableType: [
+            {value: '', label: '涓嶅彲閫�', disabled: record.commit === 'check'},
+            {value: 'radio', label: '鍗曢��'},
+            {value: 'checkbox', label: '澶氶��'},
+          ]
         }
       }
     },
@@ -112,6 +107,7 @@
       label: '琛ㄦ牸灞炴��',
       initval: wrap.tableType || '',
       required: false,
+      timestamp: new Date().getTime(),
       options: [
         {value: '', label: '涓嶅彲閫�', disabled: wrap.commit === 'check'},
         {value: 'radio', label: '鍗曢��'},
diff --git a/src/menu/components/table/normal-table/columns/index.scss b/src/menu/components/table/normal-table/columns/index.scss
index af1deb4..534355b 100644
--- a/src/menu/components/table/normal-table/columns/index.scss
+++ b/src/menu/components/table/normal-table/columns/index.scss
@@ -42,7 +42,7 @@
       }
       td:not(.ant-table-selection-column) {
         position: relative;
-        padding: 12px 8px;
+        // padding: 12px 8px;
         >.profile {
           position: absolute;
           top: 2px;
diff --git a/src/menu/datasource/index.jsx b/src/menu/datasource/index.jsx
index 10fedf6..92a16b3 100644
--- a/src/menu/datasource/index.jsx
+++ b/src/menu/datasource/index.jsx
@@ -264,6 +264,12 @@
       if (res.setting && res.setting.tableName && config.setting && !config.setting.tableName) {
         setTimeout(() => {
           MKEmitter.emit('publicTableChange', res.setting.tableName, 'init')
+        }, 100)
+      }
+
+      if ((config.type === 'card' && config.subtype === 'datacard') || (config.type === 'table' && config.subtype === 'normaltable')) {
+        setTimeout(() => {
+          MKEmitter.emit('mkUpdateInter', {uuid: config.uuid, columns: res.columns}, {delay: 0})
         }, 150)
       }
     }, () => {
diff --git a/src/menu/datasource/verifycard/index.jsx b/src/menu/datasource/verifycard/index.jsx
index 8fb10d0..f38a70b 100644
--- a/src/menu/datasource/verifycard/index.jsx
+++ b/src/menu/datasource/verifycard/index.jsx
@@ -962,13 +962,18 @@
 
   copyColumns = () => {
     const { config } = this.props
-    const { columns, setting } = this.state
+    const { columns, subColumns, setting } = this.state
 
+    let _columns = columns
     let m = []
     let n = []
     let s = []
 
-    columns.forEach(col => {
+    if (subColumns && subColumns.length) {
+      _columns = [...columns, ...subColumns]
+    }
+
+    _columns.forEach(col => {
       m.unshift(`${col.field} ${col.datatype}`)
       n.unshift(col.field)
       if (/decimal|int/ig.test(col.datatype)) {
@@ -993,7 +998,7 @@
         cols.forEach(col => {
           if (col.type === 'extend') {
             let datatype = 'Nvarchar(50)'
-            columns.forEach(c => {
+            _columns.forEach(c => {
               if (c.field === col.field) {
                 datatype = c.datatype
               }
@@ -1069,8 +1074,6 @@
   addProcess = () => {
     const { config } = this.props
     const { columns } = this.state
-
-    if (config.subtype === 'dualdatacard') return
 
     let fields = []
     let cols = []
diff --git a/src/menu/datasource/verifycard/settingform/index.jsx b/src/menu/datasource/verifycard/settingform/index.jsx
index 560e5d9..97cedeb 100644
--- a/src/menu/datasource/verifycard/settingform/index.jsx
+++ b/src/menu/datasource/verifycard/settingform/index.jsx
@@ -414,10 +414,10 @@
                 {getFieldDecorator('primaryKey', {
                   initialValue: setting.primaryKey || ''
                 })(
-                  <Select>
+                  <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>
                     {columns.map((option, i) =>
                       <Select.Option key={i} value={option.field}>
-                        {option.label}
+                        {`${option.label}锛�${option.field}锛塦}
                       </Select.Option>
                     )}
                   </Select>
@@ -652,10 +652,10 @@
                 {getFieldDecorator('subKey', {
                   initialValue: setting.subKey || ''
                 })(
-                  <Select>
+                  <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>
                     {this.props.subColumns.map((option, i) =>
                       <Select.Option key={i} value={option.field}>
-                        {option.label}
+                        {`${option.label}锛�${option.field}锛塦}
                       </Select.Option>
                     )}
                   </Select>
@@ -667,10 +667,10 @@
                 {getFieldDecorator('subBID', {
                   initialValue: setting.subBID || ''
                 })(
-                  <Select>
+                  <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>
                     {this.props.subColumns.map((option, i) =>
                       <Select.Option key={i} value={option.field}>
-                        {option.label}
+                        {`${option.label}锛�${option.field}锛塦}
                       </Select.Option>
                     )}
                   </Select>
diff --git a/src/menu/debug/index.jsx b/src/menu/debug/index.jsx
index 09c2038..c40298c 100644
--- a/src/menu/debug/index.jsx
+++ b/src/menu/debug/index.jsx
@@ -430,7 +430,7 @@
       }
     } else if (cell.OpenType === 'excelIn') {
       if (cell.intertype === 'system') {
-        sql = this.getExcelInSql(cell)
+        sql = this.getExcelInSql(cell, process)
       }
     } else if (cell.OpenType === 'excelOut') {
       if (cell.intertype === 'system' && cell.verify && cell.verify.dataType === 'custom') {
@@ -1470,17 +1470,54 @@
 
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      let numberFields = []
+      let dateFields = []
+      btn.columns.forEach((col) => {
+        if (/Nvarchar/ig.test(col.type)) {
+          textFields.push(col.Column)
+        } else if (/Decimal|int/ig.test(col.type)) {
+          numberFields.push(col.Column)
+        } else if (/date/ig.test(col.type)) {
+          dateFields.push(col.Column)
+        }
+      })
       btn.uniques.forEach(unique => {
         if (unique.status === 'false' || !unique.verifyType) return
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
-        let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
+
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
 
         if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
 
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
@@ -1494,7 +1531,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
@@ -1543,12 +1580,54 @@
 
       ${_uniquesql}
       ${_prevCustomScript}
-      ${_insert}
-      ${_backCustomScript}
+      ${_insert}`
 
-      drop table #${sheet}
-      
-      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    if (btn.workFlow === 'true' && process) {
+      if (btn.flowSql === 'true') {
+        sql += `
+        /* 宸ヤ綔娴侀粯璁ql */
+        insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
+        select jskey,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
+        from #${sheet}
+        `
+      }
+
+      sql += `
+        ${_backCustomScript}
+  
+        drop table #${sheet}
+        
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+
+      sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
+      sql = sql.replace(/@works_flow_code@/ig, `'mk'`)
+      sql = sql.replace(/@works_flow_name@/ig, `'mk'`)
+      sql = sql.replace(/@works_flow_param@/ig, `''`)
+      sql = sql.replace(/@works_flow_detail_id@/ig, `'0'`)
+      sql = sql.replace(/@status@/ig, `'888'`)
+      sql = sql.replace(/@statusname@/ig, `'缁撴潫'`)
+      sql = sql.replace(/@work_group@/ig, `'mk'`)
+      sql = sql.replace(/@work_grade@/ig, `'0'`)
+    } else {
+      sql += `
+        ${_backCustomScript}
+  
+        drop table #${sheet}
+        
+        aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
 
     return sql
   }
@@ -1662,17 +1741,54 @@
 
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      let numberFields = []
+      let dateFields = []
+      columns.forEach((col) => {
+        if (/Nvarchar/ig.test(col.datatype)) {
+          textFields.push(col.field)
+        } else if (/Decimal|int/ig.test(col.datatype)) {
+          numberFields.push(col.field)
+        } else if (/date/ig.test(col.datatype)) {
+          dateFields.push(col.field)
+        }
+      })
       btn.uniques.forEach(unique => {
         if (unique.status === 'false' || !unique.verifyType) return
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
-        let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
+
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
 
         if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
 
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
@@ -1686,7 +1802,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
diff --git a/src/menu/modalconfig/formfork/index.jsx b/src/menu/modalconfig/formfork/index.jsx
new file mode 100644
index 0000000..b7d8834
--- /dev/null
+++ b/src/menu/modalconfig/formfork/index.jsx
@@ -0,0 +1,376 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Empty, Radio } from 'antd'
+import { ForkOutlined } from '@ant-design/icons'
+
+import './index.scss'
+
+class FormFork extends Component {
+  static propTpyes = {
+    forms: PropTypes.array
+  }
+
+  state = {
+    visible: false,
+    empty: false,
+    ctrlFields: [],
+    subFields: [],
+    subRFields: [],
+    linkFields: [],
+    tabFields: [],
+    type: '',
+    forward: 'true',
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  trigger = () => {
+    const { forms } = this.props
+
+    let linkFields = {}    // 鍏宠仈鑿滃崟
+    let controlFields = {} // 鎺у埗琛ㄥ崟
+    let fieldMap = new Map()
+    let formlist = fromJS(forms).toJS()
+
+    formlist.forEach(item => {
+      if (item.supField) { // 澶氬眰琛ㄥ崟鎺у埗
+        if (['hint', 'split', 'formula'].includes(item.type)) {
+          item.field = item.uuid
+        }
+        let supvals = []
+        if (item.supvalue) {
+          item.supvalue.split(',').forEach(val => {
+            supvals.push(val)
+          })
+        } else {
+          supvals.push('')
+        }
+        supvals = Array.from(new Set(supvals))
+        controlFields[item.supField] = controlFields[item.supField] || []
+        controlFields[item.supField].push({field: item.field, values: supvals.join(','), type: item.type})
+      } else {
+        delete item.supField
+        delete item.supvalue
+      }
+      if (item.linkField) {
+        linkFields[item.linkField] = linkFields[item.linkField] || []
+        linkFields[item.linkField].push({field: item.field, label: item.label, uuid: item.uuid})
+      } else {
+        delete item.linkField
+      }
+
+      Object.keys(item).forEach(key => {
+        if (!['type', 'uuid', 'field', 'label', 'supField', 'supvalue', 'linkField', 'linkSubField', 'multiple', 'enter', 'tabField'].includes(key)) {
+          delete item[key]
+        }
+      })
+
+      if (!item.field) return
+
+      fieldMap.set(item.field, item)
+    })
+
+    Object.keys(controlFields).forEach(key => {
+      if (!fieldMap.has(key)) return
+
+      let supItem = fieldMap.get(key)
+      let fields = []
+      
+      controlFields[key].forEach(item => {
+        if (!fieldMap.has(item.field)) return
+
+        item.label = fieldMap.get(item.field).label
+
+        fields.push(item)
+      })
+
+      if (fields.length === 0) return
+
+      supItem.controlFields = fields
+      
+      fieldMap.set(key, supItem)
+    })
+
+    let _f = fromJS([...fieldMap.values()]).toJS()
+    _f.forEach(item => {
+      // 涓嬬骇琛ㄥ崟鎺у埗-瀛楁鍐欏叆
+      if (item.linkSubField && item.linkSubField.length > 0) {
+        item.subFields = []
+        if ((['select', 'radio', 'link', 'cascader'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true'))) {
+          item.linkSubField.forEach(m => {
+            let n = fieldMap.get(m)
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
+              item.subFields.push({
+                uuid: n.uuid,
+                field: m,
+                label: n.label
+              })
+            }
+          })
+        } else if (item.type === 'switch') {
+          item.linkSubField.forEach(m => {
+            let n = fieldMap.get(m)
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
+              item.subFields.push({
+                uuid: n.uuid,
+                field: m,
+                label: n.label
+              })
+            }
+          })
+        } else if (item.type === 'fileupload') {
+          item.linkSubField.forEach(m => {
+            let n = fieldMap.get(m)
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
+              item.subFields.push({
+                uuid: n.uuid,
+                field: m,
+                label: n.label
+              })
+            }
+          })
+        } else if (item.type === 'popSelect') {
+          item.linkSubField.forEach(m => {
+            let n = fieldMap.get(m)
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
+              item.subFields.push({
+                uuid: n.uuid,
+                field: m,
+                label: n.label
+              })
+            }
+          })
+        }
+
+        if (item.subFields.length === 0) {
+          delete item.subFields
+        }
+      }
+
+      if (linkFields[item.field]) {
+        item.linkFields = linkFields[item.field]
+      }
+      
+      if (item.enter === 'tab' || item.enter === 'sub') {
+        if (item.tabField) {
+          if (!fieldMap.has(item.tabField)) {
+            delete item.tabField
+          } else {
+            item.tabLabel = fieldMap.get(item.tabField).label
+          }
+        } else {
+          delete item.tabField
+        }
+      } else {
+        delete item.tabField
+      }
+
+      if (item.linkField) {
+        if (!fieldMap.has(item.linkField)) {
+          item.linkLabel = '瀛楁闆�'
+        } else {
+          item.linkLabel = fieldMap.get(item.linkField).label
+        }
+      }
+
+      delete item.enter
+      delete item.supField
+      delete item.multiple
+      delete item.linkSubField
+
+      fieldMap.set(item.field, item)
+    })
+
+    let _t = fromJS([...fieldMap.values()]).toJS()
+
+    _t.forEach(item => {
+      if (item.subFields) {
+        item.subFields.forEach(cell => {
+          let _cell = fieldMap.get(cell.field)
+
+          _cell.resubFields = _cell.resubFields || []
+          
+          _cell.resubFields.push({
+            uuid: item.uuid,
+            field: item.field,
+            label: item.label
+          })
+
+          fieldMap.set(cell.field, _cell)
+        })
+      }
+    })
+
+    let _n = [...fieldMap.values()]
+
+    let ctrlFields = []
+    let subFields = []
+    let subRFields = []
+    let _linkFields = []
+    let tabFields = []
+
+    _n.forEach(cell => {
+      if (cell.controlFields) {
+        ctrlFields.push({
+          field: cell.field,
+          label: cell.label,
+          children: cell.controlFields.map(m => {
+            return {
+              field: ['hint', 'split', 'formula'].includes(m.type) ? '' : m.field,
+              label: m.label,
+              tail: `${m.values}`
+            }
+          })
+        })
+      }
+
+      if (cell.subFields) {
+        subFields.push({
+          field: cell.field,
+          label: cell.label,
+          children: cell.subFields
+        })
+      }
+      if (cell.resubFields) {
+        subRFields.push({
+          field: cell.field,
+          label: cell.label,
+          children: cell.resubFields
+        })
+      }
+      if (cell.linkFields) {
+        _linkFields.push({
+          field: cell.field,
+          label: cell.label,
+          children: cell.linkFields
+        })
+      }
+      if (cell.tabField) {
+        tabFields.push({
+          field: cell.field,
+          label: cell.label,
+          children: [{
+            field: cell.tabField,
+            label: cell.tabLabel,
+          }]
+        })
+      }
+    })
+
+    let type = ''
+    if (ctrlFields.length > 0) {
+      type = 'ctrl'
+    } else if (subFields.length > 0) {
+      type = 'input'
+    } else if (_linkFields.length > 0) {
+      type = 'link'
+    } else if (tabFields.length > 0) {
+      type = 'switch'
+    }
+
+    this.setState({
+      type,
+      forward: 'true',
+      empty: type === '',
+      ctrlFields,
+      subFields,
+      subRFields,
+      linkFields: _linkFields,
+      tabFields,
+      visible: true
+    })
+  }
+
+  getcontent = () => {
+    const { ctrlFields, subFields, subRFields, linkFields, tabFields, visible, type, forward } = this.state
+
+    if (!visible) return null
+
+    let header = <div className="fork-tabs">
+      {ctrlFields.length ? <div onClick={() => this.setState({type: 'ctrl', forward: 'true'})} className={'tab-item' + (type === 'ctrl' ? ' active' : '')}>琛ㄥ崟鎺у埗</div> : null}
+      {subFields.length ? <div onClick={() => this.setState({type: 'input', forward: 'true'})} className={'tab-item' + (type === 'input' ? ' active' : '')}>琛ㄥ崟濉厖</div> : null}
+      {linkFields.length ? <div onClick={() => this.setState({type: 'link', forward: 'true'})} className={'tab-item' + (type === 'link' ? ' active' : '')}>琛ㄥ崟鍏宠仈</div> : null}
+      {tabFields.length ? <div onClick={() => this.setState({type: 'switch', forward: 'true'})} className={'tab-item' + (type === 'switch' ? ' active' : '')}>琛ㄥ崟鍒囨崲</div> : null}
+    </div>
+
+    let items = []
+
+    if (type === 'ctrl') {
+      items = ctrlFields
+    } else if (type === 'input') {
+      if (forward === 'true') {
+        items = subFields
+      } else {
+        items = subRFields
+      }
+    } else if (type === 'link') {
+      items = linkFields
+    } else if (type === 'switch') {
+      items = tabFields
+    }
+
+    let content = items.map((item, i) => {
+      return <div className="fork-item-wrap" key={i}>
+        <div className="fork-left">
+          <div className="fork-item">
+            <span>{item.label}</span>
+            <span>{item.field}</span>
+          </div>
+        </div>
+        <div className="fork-right">
+          {item.children.map((cell, n) => <div className="fork-item" key={n}>
+            <span>{cell.label}</span>
+            <span>{cell.field}</span>
+            {cell.tail ? <span title={cell.tail} className="fork-tail">{cell.tail}</span> : null}
+          </div>)}
+        </div>
+      </div>
+    })
+
+    return <div>
+      {header}
+      <div className="forward-wrap">
+        {type === 'ctrl' ? <div className="legend"><span>涓昏〃鍗�</span><span>鍙楁帶琛ㄥ崟</span></div> : null}
+        {type === 'input' ? <div className="legend"><span>涓昏〃鍗�</span><span>琚~鍏ヨ〃鍗�</span></div> : null}
+        {type === 'link' ? <div className="legend"><span>涓婄骇琛ㄥ崟</span><span>涓嬬骇琛ㄥ崟</span></div> : null}
+        {type === 'switch' ? <div className="legend"><span>婧愯〃鍗�</span><span>璺宠浆琛ㄥ崟</span></div> : null}
+        {type === 'input' ? <Radio.Group value={forward} onChange={(e) => this.setState({forward: e.target.value})}>
+          <Radio value="true">姝e悜</Radio>
+          <Radio value="false">鍙嶅悜</Radio>
+        </Radio.Group> : null}
+      </div>
+      <div className={'fork-wrap fork-' + forward}>
+        {content}
+      </div>
+    </div>
+  }
+
+  render() {
+    const { visible, empty } = this.state
+
+    return (
+      <>
+        <ForkOutlined title="琛ㄥ崟鍏崇郴鍥�" onClick={this.trigger}/>
+        <Modal
+          title={empty ? '琛ㄥ崟鍏崇郴鍥�' : ''}
+          wrapClassName="form-fork-modal mk-scroll-modal"
+          visible={visible}
+          width={900}
+          maskClosable={true}
+          closable={false}
+          cancelText="鍏抽棴"
+          onOk={() => { this.setState({ visible: false })}}
+          onCancel={() => { this.setState({ visible: false })}}
+          destroyOnClose
+        >
+          {empty ? <Empty description="鏃犺〃鍗曞叧鑱斾俊鎭��" /> : this.getcontent()}
+        </Modal>
+      </>
+    )
+  }
+}
+
+export default FormFork
\ No newline at end of file
diff --git a/src/menu/modalconfig/formfork/index.scss b/src/menu/modalconfig/formfork/index.scss
new file mode 100644
index 0000000..8881b09
--- /dev/null
+++ b/src/menu/modalconfig/formfork/index.scss
@@ -0,0 +1,177 @@
+.form-fork-modal {
+  .ant-modal-header {
+    text-align: center;
+  }
+  .ant-modal-body {
+    min-height: 350px!important;
+
+    .ant-empty {
+      margin-top: 50px;
+    }
+
+    .fork-tabs {
+      border-bottom: 1px solid #e8e8e8;
+      text-align: center;
+      color: rgba(0, 0, 0, 0.85);
+
+      .tab-item {
+        display: inline-block;
+        padding: 4px 12px;
+        border-bottom: 2px solid transparent;
+        transition: all 0.3s;
+        cursor: pointer;
+      }
+      .tab-item:not(:last-child) {
+        margin-right: 10px;
+      }
+      .tab-item.active {
+        border-color: #1890ff;
+      }
+    }
+    .forward-wrap {
+      position: relative;
+      padding: 5px;
+
+      .ant-radio-group {
+        position: absolute;
+        top: 5px;
+        right: 0px;
+      }
+
+      .legend {
+        span {
+          display: inline-block;
+          margin-right: 20px;
+          position: relative;
+          margin-left: 60px;
+        }
+        span::before {
+          content: ' ';
+          display: block;
+          position: absolute;
+          width: 50px;
+          height: 6px;
+          left: -55px;
+          top: 10px;
+        }
+        span:first-child::before {
+          background: #8E44AD;
+        }
+        span:last-child::before {
+          background: rgb(38, 194, 129);
+        }
+      }
+    }
+    .fork-wrap {
+      padding-top: 15px;
+    }
+    .fork-wrap.fork-false {
+      .fork-item-wrap {
+        .fork-left {
+          .fork-item {
+            border-color: rgb(38, 194, 129);
+            color: #26c281;
+          }
+        }
+        .fork-right {
+          .fork-item {
+            border-color: #8E44AD;
+            color: #8E44AD;
+          }
+        }
+      }
+    }
+    .fork-item-wrap {
+      display: inline-flex;
+      width: 50%;
+      margin-bottom: 20px;
+
+      .fork-left {
+        position: relative;
+        display: flex;
+        width: 50%;
+        align-items: center;
+        
+        .fork-item {
+          border-color: #8E44AD;
+          color: #8E44AD;
+        }
+        .fork-item::before {
+          content: '';
+          display: block;
+          border-top: 1px solid #bcbcbc;
+          position: absolute;
+          top: 28px;
+          width: 58px;
+          right: -58px;
+        }
+      }
+      .fork-right {
+        position: relative;
+        display: inline-block;
+        width: 50%;
+        padding-left: 30px;
+
+        .fork-item {
+          border-color: rgb(38, 194, 129);
+          color: #26c281;
+        }
+        .fork-item:not(:last-child) {
+          margin-bottom: 10px;
+        }
+        .fork-item::before {
+          content: '';
+          display: block;
+          border-top: 1px solid #bcbcbc;
+          position: absolute;
+          top: 28px;
+          width: 56px;
+          left: -56px;
+        }
+      }
+      .fork-right::before {
+        content: '';
+        display: block;
+        border-left: 1px solid #bcbcbc;
+        position: absolute;
+        top: 29px;
+        bottom: 27px;
+        left: -26px;
+      }
+
+      .fork-item {
+        position: relative;
+        display: block;
+        width: 130px;
+        border: 1px solid #bcbcbc;
+        padding: 5px 10px;
+        height: 56px;
+        border-radius: 4px;
+        span:not(.fork-tail) {
+          display: block;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+        .fork-tail {
+          display: inline-block;
+          position: absolute;
+          color: rgba(0, 0, 0, 0.85);
+          top: 10px;
+          right: 135px;
+          max-width: 45px;
+          display: block;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+    }
+  }
+
+  .ant-modal-footer {
+    .ant-btn-primary {
+      display: none;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/modalconfig/index.jsx b/src/menu/modalconfig/index.jsx
index 6388269..6f40e02 100644
--- a/src/menu/modalconfig/index.jsx
+++ b/src/menu/modalconfig/index.jsx
@@ -3,8 +3,8 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { Button, Card, Modal, Collapse, Switch, message } from 'antd'
-import { SettingOutlined, CopyOutlined } from '@ant-design/icons'
+import { Button, Card, Modal, Collapse, Switch, message, Popover } from 'antd'
+import { SettingOutlined, CopyOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons'
 
 import { getModalForm } from '@/templates/zshare/formconfig'
 import SourceElement from '@/templates/modalconfig/dragelement/source'
@@ -21,6 +21,7 @@
 const TableComponent = asyncComponent(() => import('./tablecomponent'))
 const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
 const PasteForms = asyncComponent(() => import('@/menu/components/share/pasteforms'))
+const FormFork = asyncComponent(() => import('@/menu/modalconfig/formfork'))
 const DragElement = asyncComponent(() => import('@/templates/modalconfig/dragelement'))
 const FieldsComponent = asyncComponent(() => import('@/templates/sharecomponent/fieldscomponent'))
 
@@ -40,7 +41,6 @@
     originConfig: null,    // 鍘熷鑿滃崟
     sqlVerifing: false,    // sql楠岃瘉
     showField: false,      // 鏄剧ず琛ㄥ崟瀛楁鍊�
-    standardform: null,
     saving: false
   }
 
@@ -61,7 +61,6 @@
 
   componentDidMount () {
     MKEmitter.addListener('completeSave', this.completeSave)
-    MKEmitter.addListener('submitStyle', this.getStyle)
   }
 
   /**
@@ -72,7 +71,6 @@
       return
     }
     MKEmitter.removeListener('completeSave', this.completeSave)
-    MKEmitter.removeListener('submitStyle', this.getStyle)
   }
 
   /**
@@ -100,121 +98,21 @@
 
   /**
    * @description 琛ㄥ崟缂栬緫
-   * 1銆佹樉绀虹紪杈戝脊绐�-visible
-   * 2銆佷繚瀛樼紪杈戦」-card
-   * 3銆佽缃紪杈戝弬鏁伴」-formlist
    */
   handleForm = (_card) => {
     const { componentConfig, btn } = this.props
     const { config } = this.state
+
     let card = fromJS(_card).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    config.fields.forEach((item, i) => {
-      if (card.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || card.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (['switch', 'check', 'popSelect'].includes(item.type)) {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-    if (index !== null) {
-      if (index === 0) {
-        standardform = config.fields[index + 1] || null
-      } else {
-        standardform = config.fields[index - 1] || null
-      }
-    }
-
     let columns = componentConfig.columns
     if (btn.$sub) {
       columns = componentConfig.subColumns || []
     }
 
-    let _fields = _linkableFields.map(cell => cell.field)
-    columns.forEach(col => {
-      if (col.field && !_fields.includes(col.field)) {
-        _linkableFields.push({
-          field: col.field,
-          label: col.label + '-鏄剧ず鍒�'
-        })
-      }
-    })
-
-    if (card.linkSubField && card.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (!card.span && standardform && standardform.span) {
-      card.span = standardform.span
-      card.labelwidth = standardform.labelwidth
-    } else if (!card.span) {
-      card.span = 12
-      card.labelwidth = 33.3
-    }
-
     this.setState({
-      standardform,
       visible: true,
       card: card,
-      formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, columns)
-    })
-  }
-
-  getStyle = (comIds, style) => {
-    const { config } = this.state
-
-    if (comIds[0] !== 'form') return
-
-    let Index = config.fields.findIndex(n => n.uuid === comIds[1])
-
-    if (Index === -1) return
-    
-    let _config = fromJS(config).toJS()
-
-    _config.fields[Index].style = style
-
-    this.setState({
-      config: _config
+      formlist: getModalForm(card, config.fields, columns)
     })
   }
 
@@ -494,7 +392,6 @@
           <div className="setting">
             <Card title="琛ㄥ崟閰嶇疆" bordered={false} extra={
               <div>
-                <Button type="danger" onClick={this.clearConfig}>娓呯┖</Button>
                 <PasteForms type="toolbar" config={config} update={this.pasteFields}/>
                 <Button type="primary" id="save-modal-config" loading={saving} onClick={this.submitConfig}>淇濆瓨</Button>
                 <Button onClick={this.cancelConfig}>杩斿洖</Button>
@@ -504,12 +401,22 @@
               <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">{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>
-                  <Button className="mk-cols-change" onClick={() => this.changecols(4)}>4鍒�</Button>
-                  <CopyOutlined title="澶嶅埗" onClick={this.triggerCopy} />
-                  <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
+                  <div className="mk-form-tool">
+                    <DeleteOutlined title="娓呯┖" onClick={this.clearConfig} />
+                    <Popover title="鍒囨崲甯冨眬" overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+                      <>
+                        <Button style={{marginRight: '10px'}} onClick={() => this.changecols(1)}>1鍒�</Button>
+                        <Button style={{marginRight: '10px'}} onClick={() => this.changecols(2)}>2鍒�</Button>
+                        <Button style={{marginRight: '10px'}} onClick={() => this.changecols(3)}>3鍒�</Button>
+                        <Button onClick={() => this.changecols(4)}>4鍒�</Button>
+                      </>
+                    } trigger="hover">
+                      <SwapOutlined />
+                    </Popover>
+                    <FormFork forms={config.fields}/>
+                    <CopyOutlined title="澶嶅埗" onClick={this.triggerCopy} />
+                    <Switch checkedChildren="寮�" unCheckedChildren="鍏�" defaultChecked={this.state.showField} onChange={(val) => this.setState({showField: val})} />
+                  </div>
                 </div>
                 <div className="ant-modal-body">
                   <div className="modal-form">
@@ -553,7 +460,7 @@
             card={card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={config.fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index 3de73e1..ce93e36 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -125,7 +125,8 @@
           z-index: 10;
           background: transparent;
           min-height: 50px;
-          padding-right: 80px;
+          padding-right: 10px;
+          
           .ant-modal-title {
             display: inline-block;
             height: 22px;
@@ -143,23 +144,6 @@
               text-align: center;
               line-height: 30px;
             }
-          }
-          .anticon-copy {
-            position: absolute;
-            top: 18px;
-            color: #26C281;
-            right: 65px;
-            font-size: 16px;
-          }
-          .ant-switch {
-            position: absolute;
-            top: 15px;
-            right: 10px;
-          }
-          .mk-cols-change {
-            float: right;
-            height: 25px;
-            margin-right: 10px;
           }
         }
         .ant-modal-close {
@@ -253,12 +237,6 @@
               bottom: 0;
               opacity: 0;
               z-index: 1;
-            }
-            .ant-col-cuslabel {
-              width: 10.5%;
-            }
-            .ant-col-cuswrap {
-              width: 89.5%;
             }
           }
         }
diff --git a/src/menu/stylecombcontroller/index.scss b/src/menu/stylecombcontroller/index.scss
index 7c91c4a..bc8fabd 100644
--- a/src/menu/stylecombcontroller/index.scss
+++ b/src/menu/stylecombcontroller/index.scss
@@ -115,34 +115,6 @@
   }
 }
 
-.margin-popover {
-  padding-top: 0px;
-  .ant-popover-inner-content {
-    width: 90px;
-    padding: 0px 5px;
-    .ant-menu-root.ant-menu-vertical {
-      border: 0;
-      .ant-menu-item {
-        height: 30px;
-        cursor: pointer;
-        line-height: 30px;
-      }
-      .ant-menu-item:not(:last-child) {
-        margin-bottom: 0px;
-      }
-      .ant-menu-item:first-child {
-        margin-top: 10px;
-      }
-      .ant-menu-item:last-child {
-        margin-bottom: 10px;
-      }
-    }
-  }
-  .ant-popover-arrow {
-    display: none;
-  }
-}
-
 .menu-style-drawer {
   .ant-drawer-body {
     height: calc(100vh - 50px);
diff --git a/src/menu/stylecontroller/index.scss b/src/menu/stylecontroller/index.scss
index df5ab73..8280649 100644
--- a/src/menu/stylecontroller/index.scss
+++ b/src/menu/stylecontroller/index.scss
@@ -156,34 +156,6 @@
   }
 }
 
-.margin-popover {
-  padding-top: 0px;
-  .ant-popover-inner-content {
-    width: 90px;
-    padding: 0px 5px;
-    .ant-menu-root.ant-menu-vertical {
-      border: 0;
-      .ant-menu-item {
-        height: 30px;
-        cursor: pointer;
-        line-height: 30px;
-      }
-      .ant-menu-item:not(:last-child) {
-        margin-bottom: 0px;
-      }
-      .ant-menu-item:first-child {
-        margin-top: 10px;
-      }
-      .ant-menu-item:last-child {
-        margin-bottom: 10px;
-      }
-    }
-  }
-  .ant-popover-arrow {
-    display: none;
-  }
-}
-
 .menu-style-drawer {
   .ant-drawer-body {
     height: calc(100vh - 50px);
diff --git a/src/mob/components/txmap/index.jsx b/src/mob/components/txmap/index.jsx
new file mode 100644
index 0000000..8962ee9
--- /dev/null
+++ b/src/mob/components/txmap/index.jsx
@@ -0,0 +1,135 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Popover } from 'antd'
+import { ToolOutlined, EditOutlined, FontColorsOutlined, DeleteOutlined, SettingOutlined } from '@ant-design/icons'
+
+import { resetStyle } from '@/utils/utils-custom.js'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import getWrapForm from './options'
+import MKEmitter from '@/utils/events.js'
+import MkMap from '@/assets/img/map.jpg'
+import './index.scss'
+
+const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+
+class MapComponent extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    updateConfig: PropTypes.func,
+    deletecomponent: PropTypes.func
+  }
+
+  state = {}
+
+  /**
+   * @description 鎼滅储鏉′欢鍒濆鍖�
+   */
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        width: 24,
+        name: card.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        wrap: { name: card.name, width: 24, datatype: 'static' },
+        style: {marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px', height: '100vh'},
+        columns: [],
+        scripts: [],
+      }
+      this.setState({
+        card: _card
+      })
+      this.props.updateConfig(_card)
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  getStyle = (style) => {
+    let _card = {...this.state.card, style}
+
+    this.setState({
+      card: _card
+    })
+    
+    this.props.updateConfig(_card)
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', ['height', 'padding', 'margin'], card.style, this.getStyle)
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (component) => {
+    this.setState({
+      card: component
+    })
+
+    component.width = component.wrap.width
+    component.name = component.wrap.name
+
+    this.props.updateConfig(component)
+  }
+
+  getWrapForms = () => {
+    const { wrap } = this.state.card
+
+    return getWrapForm(wrap)
+  }
+
+  updateWrap = (res) => {
+    this.updateComponent({...this.state.card, wrap: res})
+  }
+
+  render() {
+    const { card } = this.state
+    let _style = resetStyle(card.style)
+
+    return (
+      <div className="map-wrap" id={card.uuid} style={_style}>
+        <div className="map-image" style={{backgroundImage: `url('${MkMap}')`}}></div>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <NormalForm title="璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+              <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
+            </NormalForm>
+            <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
+            <DeleteOutlined className="close" onClick={() => this.props.deletecomponent(card.uuid)} />
+            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
+            {card.wrap.datatype === 'static' ? <SettingOutlined style={{color: '#eeeeee', cursor: 'not-allowed'}}/> : null}
+          </div>
+        } trigger="hover">
+          <ToolOutlined />
+        </Popover>
+        <div className="component-name"><div className="center">{card.name}</div></div>
+      </div>
+    )
+  }
+}
+
+export default MapComponent
\ No newline at end of file
diff --git a/src/mob/components/txmap/index.scss b/src/mob/components/txmap/index.scss
new file mode 100644
index 0000000..e43197f
--- /dev/null
+++ b/src/mob/components/txmap/index.scss
@@ -0,0 +1,35 @@
+.map-wrap {
+  min-height: 84px;
+  position: relative;
+  background: #ffffff;
+  overflow: hidden;
+
+  >.anticon-tool {
+    position: absolute;
+    z-index: 3;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+  .map-image {
+    background: #ffffff;
+    overflow: hidden;
+    background-repeat: no-repeat;
+    background-size: cover;
+    background-position: center;
+    height: 100%;
+  }
+}
+
+.map-wrap::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.map-wrap:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
\ No newline at end of file
diff --git a/src/mob/components/txmap/options.jsx b/src/mob/components/txmap/options.jsx
new file mode 100644
index 0000000..93bebd4
--- /dev/null
+++ b/src/mob/components/txmap/options.jsx
@@ -0,0 +1,28 @@
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export default function (wrap) {
+  const wrapForm = [
+    {
+      type: 'text',
+      field: 'name',
+      label: '缁勪欢鍚嶇О',
+      initval: wrap.name || '',
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'width',
+      label: '瀹藉害',
+      initval: wrap.width || 24,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      precision: 0,
+      required: true
+    }
+  ]
+
+  return wrapForm
+} 
\ No newline at end of file
diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx
index ca91322..c5a1344 100644
--- a/src/mob/mobshell/card.jsx
+++ b/src/mob/mobshell/card.jsx
@@ -31,6 +31,7 @@
 const Timeline = asyncComponent(() => import('@/menu/components/timeline/normal-timeline'))
 const OfficialAccount = asyncComponent(() => import('@/mob/components/official'))
 const ShareCode = asyncComponent(() => import('@/mob/components/sharecode'))
+const TxMap = asyncComponent(() => import('@/mob/components/txmap'))
 const Iframe = asyncComponent(() => import('@/menu/components/iframe'))
 const DoubleDataCard = asyncComponent(() => import('@/menu/components/card/double-data-card'))
 
@@ -150,6 +151,8 @@
       return (<Iframe card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'sharecode') {
       return (<ShareCode card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'map') {
+      return (<TxMap card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx
index c7b5442..257a3d7 100644
--- a/src/mob/mobshell/index.jsx
+++ b/src/mob/mobshell/index.jsx
@@ -162,6 +162,7 @@
         timeline: '鏃堕棿杞�',
         officialAccount: '鍏虫敞鍏紬鍙�',
         sharecode: '鍒嗕韩鐮�',
+        map: '鍦板浘',
         iframe: 'iframe',
         login: '鐧诲綍'
       }
diff --git a/src/mob/modalconfig/index.jsx b/src/mob/modalconfig/index.jsx
index 803af96..8ef83d0 100644
--- a/src/mob/modalconfig/index.jsx
+++ b/src/mob/modalconfig/index.jsx
@@ -38,7 +38,6 @@
     originConfig: null,    // 鍘熷鑿滃崟
     sqlVerifing: false,    // sql楠岃瘉
     showField: false,      // 鏄剧ず琛ㄥ崟瀛楁鍊�
-    standardform: null,
     saving: false
   }
 
@@ -59,7 +58,6 @@
 
   componentDidMount () {
     window.GLOB.formId = ''
-    MKEmitter.addListener('submitStyle', this.getStyle)
     MKEmitter.addListener('completeSave', this.completeSave)
   }
 
@@ -70,30 +68,11 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('submitStyle', this.getStyle)
     MKEmitter.removeListener('completeSave', this.completeSave)
   }
 
   completeSave = () => {
     this.setState({saving: false})
-  }
-
-  getStyle = (comIds, style) => {
-    const { config } = this.state
-
-    if (comIds[0] !== 'form') return
-
-    let Index = config.fields.findIndex(n => n.uuid === comIds[1])
-
-    if (Index === -1) return
-    
-    let _config = fromJS(config).toJS()
-
-    _config.fields[Index].style = style
-
-    this.setState({
-      config: _config
-    })
   }
 
   /**
@@ -127,89 +106,18 @@
   handleForm = (_card) => {
     const { componentConfig, btn } = this.props
     const { config } = this.state
+    
     let card = fromJS(_card).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    config.fields.forEach((item, i) => {
-      if (card.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || card.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (item.type === 'switch' || item.type === 'check') {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (!['select', 'link', 'radio', 'checkcard'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'checkcard' && item.multiple === 'true') return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-
-    if (index !== null) {
-      if (index === 0) {
-        standardform = config.fields[index + 1] || null
-      } else {
-        standardform = config.fields[index - 1] || null
-      }
-    }
 
     let columns = componentConfig.columns
     if (btn.$sub) {
       columns = componentConfig.subColumns || []
     }
 
-    let _fields = _linkableFields.map(cell => cell.field)
-    columns.forEach(col => {
-      if (col.field && !_fields.includes(col.field)) {
-        _linkableFields.push({
-          field: col.field,
-          label: col.label + '-鏄剧ず鍒�'
-        })
-      }
-    })
-
-    if (card.linkSubField && card.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
-    }
-
     this.setState({
-      standardform,
       visible: true,
       card: card,
-      formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields, columns)
+      formlist: getModalForm(card, config.fields, columns)
     })
   }
 
@@ -488,7 +396,7 @@
             card={card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={config.fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/mob/modalconfig/index.scss b/src/mob/modalconfig/index.scss
index d4fbaa9..67a0528 100644
--- a/src/mob/modalconfig/index.scss
+++ b/src/mob/modalconfig/index.scss
@@ -233,12 +233,6 @@
               opacity: 0;
               z-index: 1;
             }
-            .ant-col-cuslabel {
-              width: 10.5%;
-            }
-            .ant-col-cuswrap {
-              width: 89.5%;
-            }
           }
         }
         .ant-calendar-picker {
diff --git a/src/mob/modulesource/option.jsx b/src/mob/modulesource/option.jsx
index c5c6c61..9e80200 100644
--- a/src/mob/modulesource/option.jsx
+++ b/src/mob/modulesource/option.jsx
@@ -28,6 +28,7 @@
 import officialAccount from '@/assets/mobimg/guanzhu.jpg'
 import Iframe from '@/assets/img/newpage.jpg'
 import Share from '@/assets/mobimg/share.jpg'
+import MkMap from '@/assets/img/map.jpg'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
@@ -61,6 +62,7 @@
   { type: 'menu', url: SandBox, component: 'code', subtype: 'sandbox', title: '鑷畾涔�', width: 24 },
   { type: 'menu', url: group, component: 'group', subtype: 'normalgroup', title: '鍒嗙粍', width: 24 },
   { type: 'menu', url: Login, component: 'login', subtype: 'normallogin', title: '娉ㄥ唽/鐧诲綍', width: 24 },
+  { type: 'menu', url: MkMap, component: 'map', subtype: 'txmap', title: '鍦板浘', width: 24, adapter: 'mini' },
   { type: 'menu', url: officialAccount, component: 'officialAccount', subtype: 'officialAccount', title: '鍏虫敞鍏紬鍙凤紙灏忕▼搴忎腑锛�', width: 24, adapter: 'mini' },
   { type: 'menu', url: Share, component: 'sharecode', subtype: 'sharecode', title: '鍒嗕韩鐮�', width: 24 },
   { type: 'menu', url: Iframe, component: 'iframe', subtype: 'iframe', title: 'iframe', width: 24 }
diff --git a/src/mob/searchconfig/index.scss b/src/mob/searchconfig/index.scss
index de9d1a3..659c627 100644
--- a/src/mob/searchconfig/index.scss
+++ b/src/mob/searchconfig/index.scss
@@ -258,12 +258,6 @@
               opacity: 0;
               z-index: 1;
             }
-            .ant-col-cuslabel {
-              width: 10.5%;
-            }
-            .ant-col-cuswrap {
-              width: 89.5%;
-            }
           }
         }
         .ant-calendar-picker {
diff --git a/src/tabviews/basetable/index.jsx b/src/tabviews/basetable/index.jsx
index a8c9ff9..b02c94b 100644
--- a/src/tabviews/basetable/index.jsx
+++ b/src/tabviews/basetable/index.jsx
@@ -512,37 +512,45 @@
       }
     }
 
-    if (cell.verify && cell.verify.invalid === 'true') {
-      if (item.setting.maxScript && item.setting.maxScript >= 300) {
-        cell.verify.invalid = 'false'
-      } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
-        cell.verify.invalid = 'false'
-      } else if (cell.sqlType === 'insert') {
-        cell.verify.invalid = 'false'
-      } else if (cell.Ot === 'notRequired') {
-        cell.verify.invalid = 'false'
-      }
-    }
-
-    if (cell.verify && cell.verify.preHandle === 'true') {
-      let script = cell.verify.pre_func
-      if (!/#position-/.test(script) || /#position-init/.test(script)) {
-        try {
-          // eslint-disable-next-line
-          let func = new Function('btn', 'position', 'systemType', script)
-          func(cell, 'init', window.GLOB.systemType)
-        } catch (e) {
-          console.warn(e)
+    if (cell.verify) {
+      if (cell.verify.invalid === 'true') {
+        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
+          cell.verify.invalid = 'false'
+        } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
+          cell.verify.invalid = 'false'
+        } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
+          cell.verify.invalid = 'false'
+        } else if (cell.sqlType === 'insert') {
+          cell.verify.invalid = 'false'
+        } else if (cell.Ot === 'notRequired') {
+          cell.verify.invalid = 'false'
         }
       }
-      if (/#position-inner/.test(script)) {
-        cell.$innerScript = script
+
+      if (cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
+        cell.returnValue = 'true'
       }
-      if (/#position-outer/.test(script)) {
-        cell.$outerScript = script
-      }
-      if (/#position-callback/.test(script)) {
-        cell.$callbackScript = script
+
+      if (cell.verify.preHandle === 'true') {
+        let script = cell.verify.pre_func
+        if (!/#position-/.test(script) || /#position-init/.test(script)) {
+          try {
+            // eslint-disable-next-line
+            let func = new Function('btn', 'position', 'systemType', script)
+            func(cell, 'init', window.GLOB.systemType)
+          } catch (e) {
+            console.warn(e)
+          }
+        }
+        if (/#position-inner/.test(script)) {
+          cell.$innerScript = script
+        }
+        if (/#position-outer/.test(script)) {
+          cell.$outerScript = script
+        }
+        if (/#position-callback/.test(script)) {
+          cell.$callbackScript = script
+        }
       }
     }
 
diff --git a/src/tabviews/custom/components/card/balcony/index.jsx b/src/tabviews/custom/components/card/balcony/index.jsx
index 3b9b8f7..e868204 100644
--- a/src/tabviews/custom/components/card/balcony/index.jsx
+++ b/src/tabviews/custom/components/card/balcony/index.jsx
@@ -25,7 +25,6 @@
     data: {},
     BData: null,
     syncData: [],
-    show: true,
     checked: false
   }
 
@@ -112,7 +111,6 @@
       }
     }
 
-    let show = true
     let syncConfig = null
     if (_config.wrap.linkType === 'sync') {
       syncConfig = _config.syncConfig
@@ -123,12 +121,9 @@
         }
         return item
       })
-    } else if (_config.wrap.linkType === 'sup' && _config.wrap.supControl === 'hidden') {
-      show = false
     }
 
     this.setState({
-      show,
       syncConfig,
       data: _data,
       BID: BID || '',
@@ -330,10 +325,6 @@
     } else {
       if (!config.wrap.supModule || config.wrap.supModule !== MenuID) return
   
-      if (config.wrap.supControl === 'hidden') {
-        this.setState({ show: id ? true : false })
-      }
-  
       if (id !== this.state.BID || id !== '') {
         this.setState({ BID: id, BData: data }, () => {
           this.loadData()
@@ -461,9 +452,10 @@
   }
 
   render() {
-    const { config, loading, data, show, syncConfig, syncData, checked } = this.state
+    const { config, loading, data, syncConfig, syncData, checked, BID } = this.state
 
     if (config.wrap.empty === 'hidden' && (!data || data.$$empty)) return null
+    if (config.wrap.supControl === 'hidden' && !BID) return null
 
     let style = {...config.style}
     if (config.wrap.bgField) {
@@ -471,7 +463,7 @@
     }
     
     return (
-      <div className={'custom-balcony-box' + (!show ? ' hidden' : '')} id={'anchor' + config.uuid} style={style} onClick={this.triggerButton}>
+      <div className="custom-balcony-box" id={'anchor' + config.uuid} style={style} onClick={this.triggerButton}>
         {loading ?
           <div className="loading-mask" onClick={(e) => e.stopPropagation()}>
             <div className="ant-spin-blur"></div>
diff --git a/src/tabviews/custom/components/card/balcony/index.scss b/src/tabviews/custom/components/card/balcony/index.scss
index d13e2fa..b8965fb 100644
--- a/src/tabviews/custom/components/card/balcony/index.scss
+++ b/src/tabviews/custom/components/card/balcony/index.scss
@@ -66,9 +66,6 @@
     }
   }
 }
-.custom-balcony-box.hidden {
-  display: none;
-}
 
 .custom-balcony-box::after {
   content: ' ';
diff --git a/src/tabviews/custom/components/card/data-card/index.jsx b/src/tabviews/custom/components/card/data-card/index.jsx
index 1dca646..f5d8dd2 100644
--- a/src/tabviews/custom/components/card/data-card/index.jsx
+++ b/src/tabviews/custom/components/card/data-card/index.jsx
@@ -750,6 +750,10 @@
       if (config.setting.$hasSyncModule) {
         MKEmitter.emit('syncBalconyData', config.uuid, [], false)
       }
+      if (config.$hasTopModule) {
+        window.GLOB.CacheData.set(config.uuid + 'tb', { $$empty: true, $$uuid: '' })
+        MKEmitter.emit('mkPublicData', config.uuid + 'tb', { $$empty: true, $$uuid: '' })
+      }
       return
     }
 
@@ -852,6 +856,11 @@
         loading: false
       })
 
+      if (config.$hasTopModule) {
+        window.GLOB.CacheData.set(config.uuid + 'tb', data[0] || { $$empty: true, $$uuid: '' })
+        MKEmitter.emit('mkPublicData', config.uuid + 'tb', data[0] || { $$empty: true, $$uuid: '' })
+      }
+
       if (config.timer && config.clearField && result.data && result.data[0]) {
         let vals = (config.clearValue || '').split(',')
         if (vals.includes(result.data[0][config.clearField])) {
diff --git a/src/tabviews/custom/components/chart/antv-X6/index.jsx b/src/tabviews/custom/components/chart/antv-X6/index.jsx
index ad2f38a..96770b5 100644
--- a/src/tabviews/custom/components/chart/antv-X6/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-X6/index.jsx
@@ -1938,6 +1938,16 @@
           this.selectNode.attr('line/strokeDasharray', 0)
         }
       } else if (key === 'mkdata') {
+        if (!node.mkdata) {
+          if (node.target && node.target.cell) {
+            let cell = this.mkGraph.getCellById(node.target.cell)
+
+            if (cell) {
+              cell.prop('mkdata', {status: value.status, statusName: value.statusName || ''})
+            }
+          }
+        }
+
         this.selectNode.prop('mkdata', value)
       }
     } else if (node.shape === 'lane') {
diff --git a/src/tabviews/custom/components/module/invoice/index.jsx b/src/tabviews/custom/components/module/invoice/index.jsx
index e50407c..ad7b49b 100644
--- a/src/tabviews/custom/components/module/invoice/index.jsx
+++ b/src/tabviews/custom/components/module/invoice/index.jsx
@@ -541,6 +541,22 @@
   outBill = () => {
     const { config, BID, saveType } = this.state
 
+    if (window.GLOB.storeFiles) {
+      if (!window.GLOB.storeDate || window.GLOB.storeDate < 0) {
+        Modal.warning({
+          title: `鐢靛瓙妗f瀛樺偍鍖呭凡杩囨湡銆俙,
+          okText: '鐭ラ亾浜�'
+        })
+        return
+      } else if (window.GLOB.storeDate < 30) {
+        notification.warning({
+          top: 92,
+          message: `鐢靛瓙妗f瀛樺偍鍖呰繕鍓�${window.GLOB.storeDate}澶┿�俙,
+          duration: 5
+        })
+      }
+    }
+
     if (window.GLOB.systemType === 'production' && !config.billOutBtn.proInterface) {
       notification.warning({
         top: 92,
@@ -797,6 +813,10 @@
 
     param.data.invoiceTypeCode = trans[param.data.invoiceTypeCode] || ''
 
+    if (window.GLOB.storeFiles) {
+      param.store = true
+    }
+
     let url = ''
     if (window.GLOB.systemType === 'production') {
       url = config.billOutBtn.proInterface
diff --git a/src/tabviews/custom/components/table/base-table/index.jsx b/src/tabviews/custom/components/table/base-table/index.jsx
index bc2b635..10d0453 100644
--- a/src/tabviews/custom/components/table/base-table/index.jsx
+++ b/src/tabviews/custom/components/table/base-table/index.jsx
@@ -110,9 +110,9 @@
       
       MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
       reset && MKEmitter.emit('resetTable', config.uuid, 'true') // 鍒楄〃閲嶇疆
-      if (setting.$hasSyncModule) {
-        MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-      }
+      // if (setting.$hasSyncModule) {
+      //   MKEmitter.emit('syncBalconyData', config.uuid, [], false)
+      // }
 
       this.requestId = ''
       return
@@ -173,9 +173,9 @@
         }
       } else {
         MKEmitter.emit('resetSelectLine', config.uuid, '', '') // 骞挎挱鏁版嵁鍒囨崲
-        if (setting.$hasSyncModule) {
-          MKEmitter.emit('syncBalconyData', config.uuid, [], false)
-        }
+        // if (setting.$hasSyncModule) {
+        //   MKEmitter.emit('syncBalconyData', config.uuid, [], false)
+        // }
       }
       
       reset && MKEmitter.emit('resetTable', config.uuid, repage) // 鍒楄〃閲嶇疆
diff --git a/src/tabviews/custom/components/table/normal-table/index.jsx b/src/tabviews/custom/components/table/normal-table/index.jsx
index fd31261..a5e10c5 100644
--- a/src/tabviews/custom/components/table/normal-table/index.jsx
+++ b/src/tabviews/custom/components/table/normal-table/index.jsx
@@ -530,6 +530,10 @@
       if (setting.$hasSyncModule) {
         MKEmitter.emit('syncBalconyData', config.uuid, [], false)
       }
+      if (config.$hasTopModule) {
+        window.GLOB.CacheData.set(config.uuid + 'tb', { $$empty: true, $$uuid: '' })
+        MKEmitter.emit('mkPublicData', config.uuid + 'tb', { $$empty: true, $$uuid: '' })
+      }
 
       this.loaded = true
       this.requestId = ''
@@ -653,6 +657,11 @@
         loading: false
       })
 
+      if (config.$hasTopModule) {
+        window.GLOB.CacheData.set(config.uuid + 'tb', data[0] || { $$empty: true, $$uuid: '' })
+        MKEmitter.emit('mkPublicData', config.uuid + 'tb', data[0] || { $$empty: true, $$uuid: '' })
+      }
+      
       if (config.timer && config.clearField && result.data && result.data[0]) {
         let vals = (config.clearValue || '').split(',')
         if (vals.includes(result.data[0][config.clearField])) {
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index b56749d..9d8a16c 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -204,6 +204,7 @@
       // 鏉冮檺杩囨护
       let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
       let balMap = new Map()
+      let tbMap = new Map()
       let skip = config.permission === 'false' || window.GLOB.mkHS
       let urlparam = {} // url鍙傛暟
       if (param) {
@@ -261,7 +262,7 @@
       let initInters = []
 
       config.interfaces = this.formatInterSetting(config.interfaces, regs, MenuID, initInters, config.MenuName)
-      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, skip, urlparam, MenuID, config.interfaces, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true')
+      config.components = this.filterComponent(config.components, roleId, window.GLOB.mkActions, balMap, tbMap, skip, urlparam, MenuID, config.$cache, config.$time, config.MenuName, MenuID, MenuID, config.process === 'true', regs)
 
       let params = []
       let BID = urlparam.$BID || ''
@@ -284,11 +285,7 @@
         }
       })
 
-      config.components = this.formatSetting(config.components, params, inherit, regs, balMap)
-
-      if (balMap.size > 0) {
-        config.components = this.filterBalcony(config.components, balMap)
-      }
+      config.components = this.formatSetting(config.components, params, inherit, config.interfaces, balMap, tbMap)
 
       if (initInters.length > 0) {
         this.stepInter = {
@@ -380,7 +377,7 @@
     }
   }
 
-  filterComponent = (components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, searchId, syncId, process) => {
+  filterComponent = (components, roleId, permAction, balMap, tbMap, skip, urlparam, pageId, cache, time, MenuName, searchId, syncId, process, regs) => {
     return components.filter(item => {
       item.$pageId = pageId
       item.$searchId = searchId
@@ -497,7 +494,7 @@
             _searchId = tab.uuid
           }
 
-          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, _searchId, tab.uuid, process)
+          tab.components = this.filterComponent(tab.components, roleId, permAction, balMap, tbMap, skip, urlparam, pageId, cache, time, MenuName, _searchId, tab.uuid, process, regs)
           
           if (_searchId === tab.uuid) {
             tab.components.forEach(cell => {
@@ -521,7 +518,7 @@
           return false
         }
 
-        item.components = this.filterComponent(item.components, roleId, permAction, balMap, skip, urlparam, pageId, interfaces, cache, time, MenuName, searchId, syncId, process)
+        item.components = this.filterComponent(item.components, roleId, permAction, balMap, tbMap, skip, urlparam, pageId, cache, time, MenuName, searchId, syncId, process, regs)
 
         return true
       } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart', 'antvG6', 'antvX6'].includes(item.type)) {
@@ -537,16 +534,6 @@
           item.wrap.blacklist.filter(v => roleId.indexOf(v) > -1).length > 0
         ) {
           return false
-        }
-
-        if (item.wrap.datatype === 'public') {
-          let inter = interfaces.filter(int => item.wrap.publicId === int.uuid)[0]
-          if (!inter) {
-            item.wrap.datatype = 'static'
-          } else {
-            item.setting = {...inter.setting}
-            item.$searchId = inter.$searchId
-          }
         }
       }
 
@@ -785,6 +772,9 @@
           item.wrap.supModule = item.wrap.supModule.pop()
           item.setting.supModule = item.wrap.supModule
         }
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.elements = item.elements.filter(cell => {
           if (cell.eleType === 'button') {
             if (cell.hidden === 'true') return false
@@ -843,43 +833,91 @@
           item.wrap.supModule = ''
         }
       }
+
+      // 鏁寸悊鏁版嵁婧�
+      if (item.setting && item.format && (!item.wrap || !['public', 'static'].includes(item.wrap.datatype))) {
+        item.setting.arr_field = item.columns ? item.columns.map(col => col.field).join(',') : ''
+        item.setting.useMSearch = item.setting.useMSearch === 'true'
+        item.setting.laypage = item.setting.laypage === 'true'   // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡
+
+        if (item.wrap && item.wrap.goback === 'true') {
+          item.setting.sync = 'false'
+        }
+
+        if (item.format === 'object') {
+          item.setting.laypage = false
+          item.setting.$top = true
+        }
+
+        if (item.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
+          item.setting.sync = 'false'
+          item.setting.dataresource = ''
+        } else {
+          let _customScript = ''
+          let _tailScript = ''
+          item.scripts && item.scripts.forEach(script => {
+            if (script.status === 'false') return
+            if (script.position !== 'back') {
+              _customScript += `
+              ${script.sql}
+              `
+            } else {
+              _tailScript += `
+              ${script.sql}
+              `
+            }
+          })
+          delete item.scripts
+          item.setting.$name = item.$menuname || ''
+          item.setting.execute = item.setting.execute !== 'false'  // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
+          
+          if (!item.setting.execute) {
+            item.setting.dataresource = ''
+          }
+          if (/\s/.test(item.setting.dataresource)) {
+            item.setting.dataresource = '(' + item.setting.dataresource + ') tb'
+          }
       
-      return true
-    })
-  }
+          if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+            item.setting.dataresource = item.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+          } else {
+            item.setting.dataresource = item.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+          }
 
-  filterBalcony = (components, balMap) => {
-    return components.filter(item => {
-      if (item.type === 'tabs') {
-        item.subtabs = item.subtabs.map(tab => {
-          tab.components = this.filterBalcony(tab.components, balMap)
-          return tab
-        })
-      } else if (item.type === 'group') {
-        item.components = this.filterBalcony(item.components, balMap)
-      }
+          regs.forEach(cell => {
+            item.setting.dataresource = item.setting.dataresource.replace(cell.reg, cell.value)
+            _customScript = _customScript.replace(cell.reg, cell.value)
+            _tailScript = _tailScript.replace(cell.reg, cell.value)
+          })
 
-      if (item.type === 'balcony' && item.wrap.linkType === 'sync') {
-        let conf = balMap.get(item.wrap.syncModuleId)
+          item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+          item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-        if (!conf || conf === true) {
-          return false
-        }
-        
-        item.syncConfig = {
-          uuid: conf.uuid,
-          wrap: conf.wrap,
-          setting: conf.setting,
-          columns: conf.columns
-        }
+          item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
 
-        if (item.wrap.checkAll === 'show') {
-          if (conf.subtype === 'datacard' && conf.wrap.cardType !== 'checkbox') {
-            item.wrap.checkAll = 'hidden'
-          } else if (conf.subtype === 'normaltable' && conf.wrap.tableType !== 'checkbox') {
-            item.wrap.checkAll = 'hidden'
+          if (!item.setting.execute || item.setting.custompage) {
+            item.forbidLine = true
+          }
+
+          if (item.setting.sync === 'true') {
+            // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
+            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true') {
+
+            } else {
+              item.setting.sync = 'false'
+            }
           }
         }
+      }
+
+      if (item.type === 'card' && item.subtype === 'datacard') {
+        tbMap.set(item.uuid, item)
+      } else if (item.type === 'table' && item.subtype !== 'editable') {
+        tbMap.set(item.uuid, item)
       }
       
       return true
@@ -931,39 +969,45 @@
       cell.modal.uuid = cell.uuid + 'pop'
     }
 
-    if (cell.verify && cell.verify.invalid === 'true') {
-      if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
-        cell.verify.invalid = 'false'
-      } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
-        cell.verify.invalid = 'false'
-      } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
-        cell.verify.invalid = 'false'
-      } else if (cell.sqlType === 'insert') {
-        cell.verify.invalid = 'false'
-      } else if (cell.Ot === 'notRequired') {
-        cell.verify.invalid = 'false'
-      }
-    }
-
-    if (cell.verify && cell.verify.preHandle === 'true') {
-      let script = cell.verify.pre_func
-      if (!/#position-/.test(script) || /#position-init/.test(script)) {
-        try {
-          // eslint-disable-next-line
-          let func = new Function('btn', 'position', 'systemType', script)
-          func(cell, 'init', window.GLOB.systemType)
-        } catch (e) {
-          console.warn(e)
+    if (cell.verify) {
+      if (cell.verify.invalid === 'true') {
+        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
+          cell.verify.invalid = 'false'
+        } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
+          cell.verify.invalid = 'false'
+        } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
+          cell.verify.invalid = 'false'
+        } else if (cell.sqlType === 'insert') {
+          cell.verify.invalid = 'false'
+        } else if (cell.Ot === 'notRequired') {
+          cell.verify.invalid = 'false'
         }
       }
-      if (/#position-inner/.test(script)) {
-        cell.$innerScript = script
+
+      if (cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
+        cell.returnValue = 'true'
       }
-      if (/#position-outer/.test(script)) {
-        cell.$outerScript = script
-      }
-      if (/#position-callback/.test(script)) {
-        cell.$callbackScript = script
+
+      if (cell.verify.preHandle === 'true') {
+        let script = cell.verify.pre_func
+        if (!/#position-/.test(script) || /#position-init/.test(script)) {
+          try {
+            // eslint-disable-next-line
+            let func = new Function('btn', 'position', 'systemType', script)
+            func(cell, 'init', window.GLOB.systemType)
+          } catch (e) {
+            console.warn(e)
+          }
+        }
+        if (/#position-inner/.test(script)) {
+          cell.$innerScript = script
+        }
+        if (/#position-outer/.test(script)) {
+          cell.$outerScript = script
+        }
+        if (/#position-callback/.test(script)) {
+          cell.$callbackScript = script
+        }
       }
     }
 
@@ -1083,20 +1127,64 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, inherit, regs, balMap) => {
+  formatSetting = (components, params, inherit, interfaces, balMap, tbMap) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, inherit, regs, balMap)
+          tab.components = this.formatSetting(tab.components, null, inherit, interfaces, balMap, tbMap)
           tab = {...tab, ...inherit}
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, params, null, regs, balMap)
+        component.components = this.formatSetting(component.components, params, null, interfaces, balMap, tbMap)
         return component
-      } else if (component.wrap && component.wrap.datatype === 'public') {
+      }
+
+      if (component.type === 'balcony') {
+        if (component.wrap.linkType === 'sync') {
+          let conf = tbMap.get(component.wrap.syncModuleId)
+  
+          if (conf) {
+            component.syncConfig = {
+              uuid: conf.uuid,
+              wrap: conf.wrap,
+              setting: conf.setting,
+              columns: conf.columns
+            }
+    
+            if (component.wrap.checkAll === 'show') {
+              if (conf.subtype === 'datacard' && conf.wrap.cardType !== 'checkbox') {
+                component.wrap.checkAll = 'hidden'
+              } else if (conf.subtype === 'normaltable' && conf.wrap.tableType !== 'checkbox') {
+                component.wrap.checkAll = 'hidden'
+              }
+            }
+          }
+        }
+      } else if (balMap.has(component.uuid)) {
+        component.setting.$hasSyncModule = true
+      }
+      if (balMap.has(component.uuid + 'public')) {
+        component.$hasTopModule = true
+      }
+      
+      if (component.wrap && component.wrap.datatype === 'public') {
+        if (tbMap.has(component.wrap.publicId)) {
+          let tb = tbMap.get(component.wrap.publicId)
+          component.setting = {...tb.setting}
+          component.$searchId = tb.$searchId
+          component.wrap.publicId = component.wrap.publicId + 'tb'
+        } else {
+          let inter = interfaces.filter(int => component.wrap.publicId === int.uuid)[0]
+          if (!inter) {
+            component.wrap.datatype = 'static'
+          } else {
+            component.setting = {...inter.setting}
+            component.$searchId = inter.$searchId
+          }
+        }
         return component
       } else if (component.wrap && component.wrap.datatype === 'static') {
         component.format = ''
@@ -1109,10 +1197,6 @@
         return component
       }
 
-      component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
-      component.setting.useMSearch = component.setting.useMSearch === 'true'
-      component.setting.laypage = component.setting.laypage === 'true'   // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡
-      
       if (component.setting.useMSearch) {
         if (!window.GLOB.SearchBox.has(component.$searchId)) {
           component.setting.useMSearch = false
@@ -1127,79 +1211,7 @@
         }
       }
 
-      if (component.wrap && component.wrap.goback === 'true') {
-        component.setting.sync = 'false'
-      }
-
-      if (component.format === 'object') {
-        component.setting.laypage = false
-        component.setting.$top = true
-      }
-
-      if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
-        component.setting.sync = 'false'
-        component.setting.dataresource = ''
-        return component
-      }
-
-      let _customScript = ''
-      let _tailScript = ''
-      component.scripts && component.scripts.forEach(script => {
-        if (script.status === 'false') return
-        if (script.position !== 'back') {
-          _customScript += `
-          ${script.sql}
-          `
-        } else {
-          _tailScript += `
-          ${script.sql}
-          `
-        }
-      })
-      delete component.scripts
-      component.setting.$name = component.$menuname || ''
-      component.setting.execute = component.setting.execute !== 'false'  // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
-      
-      if (!component.setting.execute) {
-        component.setting.dataresource = ''
-      }
-      if (/\s/.test(component.setting.dataresource)) {
-        component.setting.dataresource = '(' + component.setting.dataresource + ') tb'
-      }
-  
-      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-      } else {
-        component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-      }
-
-      regs.forEach(cell => {
-        component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
-        _customScript = _customScript.replace(cell.reg, cell.value)
-        _tailScript = _tailScript.replace(cell.reg, cell.value)
-      })
-
-      component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
-      component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
-
-      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
-
-      if (!component.setting.execute || component.setting.custompage) {
-        component.forbidLine = true
-      }
-
-      if (component.setting.sync === 'true') {
-        // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-        if ((!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true') {
-
-        } else {
-          component.setting.sync = 'false'
-        }
-      }
+      if (component.setting.interType !== 'system') return component
 
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
@@ -1229,11 +1241,6 @@
       
       component.setting.delay = delay
       delay += 20
-
-      if (balMap.has(component.uuid)) {
-        component.setting.$hasSyncModule = true
-        balMap.set(component.uuid, component)
-      }
 
       return component
     })
diff --git a/src/tabviews/custom/popview/index.jsx b/src/tabviews/custom/popview/index.jsx
index 4213bf9..ff072e0 100644
--- a/src/tabviews/custom/popview/index.jsx
+++ b/src/tabviews/custom/popview/index.jsx
@@ -106,6 +106,7 @@
     // 鏉冮檺杩囨护
     let roleId = sessionStorage.getItem('role_id') || '' // 瑙掕壊ID
     let balMap = new Map()
+    let tbMap = new Map()
     let urlparam = {} // url鍙傛暟
     if (param) {
       Object.keys(param).forEach(key => {
@@ -139,7 +140,7 @@
       regs.push({ reg: /@works_flow_code@/ig, value: `'${flow.flow_code || ''}'` })
     }
 
-    config.components = this.filterComponent(config.components, roleId, balMap, urlparam, Tab, Tab.uuid, Tab.uuid)
+    config.components = this.filterComponent(config.components, roleId, balMap, tbMap, urlparam, Tab, Tab.uuid, Tab.uuid, regs)
     
     // 鑾峰彇涓绘悳绱㈡潯浠�
     config.components.forEach(component => {
@@ -155,11 +156,7 @@
     let params = []
     let BID = urlparam.$BID || ''
 
-    config.components = this.formatSetting(config.components, params, regs, balMap)
-
-    if (balMap.size > 0) {
-      config.components = this.filterBalcony(config.components, balMap)
-    }
+    config.components = this.formatSetting(config.components, params, balMap, tbMap)
 
     this.setState({
       BID: BID,
@@ -171,7 +168,7 @@
     })
   }
 
-  filterComponent = (components, roleId, balMap, urlparam, Tab, searchId, syncId) => {
+  filterComponent = (components, roleId, balMap, tbMap, urlparam, Tab, searchId, syncId, regs) => {
     return components.filter(item => {
       item.$pageId = Tab.uuid
       item.$searchId = searchId
@@ -271,7 +268,7 @@
             _searchId = tab.uuid
           }
 
-          tab.components = this.filterComponent(tab.components, roleId, balMap, urlparam, Tab, _searchId, tab.uuid)
+          tab.components = this.filterComponent(tab.components, roleId, balMap, tbMap, urlparam, Tab, _searchId, tab.uuid, regs)
 
           if (_searchId === tab.uuid) {
             tab.components.forEach(cell => {
@@ -295,7 +292,7 @@
           return false
         }
 
-        item.components = this.filterComponent(item.components, roleId, balMap, urlparam, Tab, searchId, syncId)
+        item.components = this.filterComponent(item.components, roleId, balMap, tbMap, urlparam, Tab, searchId, syncId, regs)
 
         return true
       } else if (['pie', 'bar', 'line', 'dashboard', 'scatter', 'chart'].includes(item.type)) {
@@ -501,6 +498,9 @@
           item.wrap.supModule = item.wrap.supModule.pop()
           item.setting.supModule = item.wrap.supModule
         }
+        if (item.wrap.datatype === 'public') {
+          balMap.set(item.wrap.publicId + 'public', true)
+        }
         item.elements = item.elements.filter(cell => {
           if (cell.eleType === 'button') {
             if (cell.hidden === 'true' || cell.OpenType === 'popview') return false
@@ -545,43 +545,91 @@
           return group
         })
       }
+
+      // 鏁寸悊鏁版嵁婧�
+      if (item.setting && item.format && (!item.wrap || !['public', 'static'].includes(item.wrap.datatype))) {
+        item.setting.arr_field = item.columns ? item.columns.map(col => col.field).join(',') : ''
+        item.setting.useMSearch = item.setting.useMSearch === 'true'
+        item.setting.laypage = item.setting.laypage === 'true'   // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡
+
+        if (item.wrap && item.wrap.goback === 'true') {
+          item.setting.sync = 'false'
+        }
+
+        if (item.format === 'object') {
+          item.setting.laypage = false
+          item.setting.$top = true
+        }
+
+        if (item.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
+          item.setting.sync = 'false'
+          item.setting.dataresource = ''
+        } else {
+          let _customScript = ''
+          let _tailScript = ''
+          item.scripts && item.scripts.forEach(script => {
+            if (script.status === 'false') return
+            if (script.position !== 'back') {
+              _customScript += `
+              ${script.sql}
+              `
+            } else {
+              _tailScript += `
+              ${script.sql}
+              `
+            }
+          })
+          delete item.scripts
+          item.setting.$name = item.$menuname || ''
+          item.setting.execute = item.setting.execute !== 'false'  // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
+          
+          if (!item.setting.execute) {
+            item.setting.dataresource = ''
+          }
+          if (/\s/.test(item.setting.dataresource)) {
+            item.setting.dataresource = '(' + item.setting.dataresource + ') tb'
+          }
       
-      return true
-    })
-  }
+          if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
+            item.setting.dataresource = item.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+            _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
+          } else {
+            item.setting.dataresource = item.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+            _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
+          }
 
-  filterBalcony = (components, balMap) => {
-    return components.filter(item => {
-      if (item.type === 'tabs') {
-        item.subtabs = item.subtabs.map(tab => {
-          tab.components = this.filterBalcony(tab.components, balMap)
-          return tab
-        })
-      } else if (item.type === 'group') {
-        item.components = this.filterBalcony(item.components, balMap)
-      }
+          regs.forEach(cell => {
+            item.setting.dataresource = item.setting.dataresource.replace(cell.reg, cell.value)
+            _customScript = _customScript.replace(cell.reg, cell.value)
+            _tailScript = _tailScript.replace(cell.reg, cell.value)
+          })
 
-      if (item.type === 'balcony' && item.wrap.linkType === 'sync') {
-        let conf = balMap.get(item.wrap.syncModuleId)
+          item.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
+          item.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
 
-        if (!conf || conf === true) {
-          return false
-        }
-        
-        item.syncConfig = {
-          uuid: conf.uuid,
-          wrap: conf.wrap,
-          setting: conf.setting,
-          columns: conf.columns
-        }
+          item.setting.custompage = /@pageSize@|@orderBy@/i.test(item.setting.dataresource + item.setting.customScript)
 
-        if (item.wrap.checkAll === 'show') {
-          if (conf.subtype === 'datacard' && conf.wrap.cardType !== 'checkbox') {
-            item.wrap.checkAll = 'hidden'
-          } else if (conf.subtype === 'normaltable' && conf.wrap.tableType !== 'checkbox') {
-            item.wrap.checkAll = 'hidden'
+          if (!item.setting.execute || item.setting.custompage) {
+            item.forbidLine = true
+          }
+
+          if (item.setting.sync === 'true') {
+            // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
+            if ((!item.pageable || (item.pageable && !item.setting.laypage)) && item.setting.onload === 'true') {
+
+            } else {
+              item.setting.sync = 'false'
+            }
           }
         }
+      }
+
+      if (item.type === 'card' && item.subtype === 'datacard') {
+        tbMap.set(item.uuid, item)
+      } else if (item.type === 'table' && item.subtype !== 'editable') {
+        tbMap.set(item.uuid, item)
       }
       
       return true
@@ -628,39 +676,45 @@
       }
     }
 
-    if (cell.verify && cell.verify.invalid === 'true') {
-      if (item.wrap && item.wrap.datatype === 'static') {
-        cell.verify.invalid = 'false'
-      } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
-        cell.verify.invalid = 'false'
-      } else if (cell.sqlType === 'insert') {
-        cell.verify.invalid = 'false'
-      } else if (cell.Ot === 'notRequired') {
-        cell.verify.invalid = 'false'
-      } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
-        cell.verify.invalid = 'false'
-      }
-    }
-
-    if (cell.verify && cell.verify.preHandle === 'true') {
-      let script = cell.verify.pre_func
-      if (!/#position-/.test(script) || /#position-init/.test(script)) {
-        try {
-          // eslint-disable-next-line
-          let func = new Function('btn', 'position', 'systemType', script)
-          func(cell, 'init', window.GLOB.systemType)
-        } catch (e) {
-          console.warn(e)
+    if (cell.verify) {
+      if (cell.verify.invalid === 'true') {
+        if (item.wrap && (item.wrap.datatype === 'static' || item.wrap.datatype === 'public')) {
+          cell.verify.invalid = 'false'
+        } else if (item.setting && item.setting.maxScript && item.setting.maxScript >= 300) {
+          cell.verify.invalid = 'false'
+        } else if (cell.intertype !== 'system' && cell.procMode !== 'system') {
+          cell.verify.invalid = 'false'
+        } else if (cell.sqlType === 'insert') {
+          cell.verify.invalid = 'false'
+        } else if (cell.Ot === 'notRequired') {
+          cell.verify.invalid = 'false'
         }
       }
-      if (/#position-inner/.test(script)) {
-        cell.$innerScript = script
+
+      if (cell.verify.linkEnable === 'true' && /@/.test(cell.verify.linkUrl)) {
+        cell.returnValue = 'true'
       }
-      if (/#position-outer/.test(script)) {
-        cell.$outerScript = script
-      }
-      if (/#position-callback/.test(script)) {
-        cell.$callbackScript = script
+
+      if (cell.verify.preHandle === 'true') {
+        let script = cell.verify.pre_func
+        if (!/#position-/.test(script) || /#position-init/.test(script)) {
+          try {
+            // eslint-disable-next-line
+            let func = new Function('btn', 'position', 'systemType', script)
+            func(cell, 'init', window.GLOB.systemType)
+          } catch (e) {
+            console.warn(e)
+          }
+        }
+        if (/#position-inner/.test(script)) {
+          cell.$innerScript = script
+        }
+        if (/#position-outer/.test(script)) {
+          cell.$outerScript = script
+        }
+        if (/#position-callback/.test(script)) {
+          cell.$callbackScript = script
+        }
       }
     }
 
@@ -760,20 +814,63 @@
   }
 
   // 鏍煎紡鍖栭粯璁よ缃�
-  formatSetting = (components, params, regs, balMap) => {
+  formatSetting = (components, params, balMap, tbMap) => {
     let delay = 20
     return components.map(component => {
       if (component.type === 'tabs') {
         component.subtabs = component.subtabs.map(tab => {
-          tab.components = this.formatSetting(tab.components, null, regs, balMap)
+          tab.components = this.formatSetting(tab.components, null, balMap, tbMap)
           return tab
         })
         return component
       } else if (component.type === 'group') {
-        component.components = this.formatSetting(component.components, params, regs, balMap)
+        component.components = this.formatSetting(component.components, params, balMap, tbMap)
         return component
-      } else if (component.wrap && (component.wrap.datatype === 'static' || component.wrap.datatype === 'public')) {
-        component.wrap.datatype = 'static'
+      }
+
+      if (component.type === 'balcony') {
+        if (component.wrap.linkType === 'sync') {
+          let conf = tbMap.get(component.wrap.syncModuleId)
+  
+          if (conf) {
+            component.syncConfig = {
+              uuid: conf.uuid,
+              wrap: conf.wrap,
+              setting: conf.setting,
+              columns: conf.columns
+            }
+    
+            if (component.wrap.checkAll === 'show') {
+              if (conf.subtype === 'datacard' && conf.wrap.cardType !== 'checkbox') {
+                component.wrap.checkAll = 'hidden'
+              } else if (conf.subtype === 'normaltable' && conf.wrap.tableType !== 'checkbox') {
+                component.wrap.checkAll = 'hidden'
+              }
+            }
+          }
+        }
+      } else if (balMap.has(component.uuid)) {
+        component.setting.$hasSyncModule = true
+      }
+
+      if (balMap.has(component.uuid + 'public')) {
+        component.$hasTopModule = true
+      }
+      
+      if (component.wrap && component.wrap.datatype === 'public') {
+        if (tbMap.has(component.wrap.publicId)) {
+          let tb = tbMap.get(component.wrap.publicId)
+          component.setting = {...tb.setting}
+          component.$searchId = tb.$searchId
+          component.wrap.publicId = component.wrap.publicId + 'tb'
+        } else {
+          component.wrap.datatype = 'static'
+          component.setting = component.setting || {}
+          component.setting.useMSearch = false
+          component.setting.sync = 'false'
+        }
+        return component
+      } else if (component.wrap && component.wrap.datatype === 'static') {
         component.format = ''
         component.setting = component.setting || {}
         component.setting.useMSearch = false
@@ -784,10 +881,6 @@
         return component
       }
 
-      component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
-      component.setting.useMSearch = component.setting.useMSearch === 'true'
-      component.setting.laypage = component.setting.laypage === 'true'   // 鏄惁鍒嗛〉锛岃浆涓篵oolean 缁熶竴鏍煎紡
-
       if (component.setting.useMSearch) {
         if (!window.GLOB.SearchBox.has(component.$searchId)) {
           component.setting.useMSearch = false
@@ -796,75 +889,7 @@
         }
       }
 
-      if (component.format === 'object') {
-        component.setting.laypage = false
-        component.setting.$top = true
-      }
-
-      if (component.setting.interType !== 'system') { // 涓嶄娇鐢ㄧ郴缁熷嚱鏁版椂
-        component.setting.sync = 'false'
-        component.setting.dataresource = ''
-        return component
-      }
-
-      let _customScript = ''
-      let _tailScript = ''
-      component.scripts && component.scripts.forEach(script => {
-        if (script.status === 'false') return
-        if (script.position !== 'back') {
-          _customScript += `
-          ${script.sql}
-          `
-        } else {
-          _tailScript += `
-          ${script.sql}
-          `
-        }
-      })
-      delete component.scripts
-      component.setting.$name = component.$menuname || ''
-      component.setting.execute = component.setting.execute !== 'false'  // 榛樿sql鏄惁鎵ц锛岃浆涓篵oolean 缁熶竴鏍煎紡
-
-      if (!component.setting.execute) {
-        component.setting.dataresource = ''
-      }
-      if (/\s/.test(component.setting.dataresource)) {
-        component.setting.dataresource = '(' + component.setting.dataresource + ') tb'
-      }
-  
-      if (sessionStorage.getItem('dataM') === 'true') { // 鏁版嵁鏉冮檺
-        component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-        _customScript = _customScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-        _tailScript = _tailScript.replace(/\$@/ig, '/*').replace(/@\$/ig, '*/').replace(/@datam@/ig, '\'Y\'')
-      } else {
-        component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-        _customScript = _customScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-        _tailScript = _tailScript.replace(/@\$|\$@/ig, '').replace(/@datam@/ig, '\'\'')
-      }
-
-      regs.forEach(cell => {
-        component.setting.dataresource = component.setting.dataresource.replace(cell.reg, cell.value)
-        _customScript = _customScript.replace(cell.reg, cell.value)
-        _tailScript = _tailScript.replace(cell.reg, cell.value)
-      })
-
-      component.setting.customScript = _customScript // 鏁寸悊鍚庤嚜瀹氫箟鑴氭湰
-      component.setting.tailScript = _tailScript     // 鍚庣疆鑷畾涔夎剼鏈�
-
-      component.setting.custompage = /@pageSize@|@orderBy@/i.test(component.setting.dataresource + component.setting.customScript)
-
-      if (!component.setting.execute || component.setting.custompage) {
-        component.forbidLine = true
-      }
-
-      if (component.setting.sync === 'true') {
-        // pageable 鏄惁鍒嗛〉锛岀粍浠跺睘鎬э紝涓嶅垎椤电殑缁勪欢鎵嶅彲浠ョ粺涓�鏌ヨ
-        if ((!component.pageable || (component.pageable && !component.setting.laypage)) && component.setting.onload === 'true') {
-
-        } else {
-          component.setting.sync = 'false'
-        }
-      }
+      if (component.setting.interType !== 'system') return component
 
       // dataName 绯荤粺鐢熸垚鐨勬暟鎹簮鍚嶇О
       if (component.setting.sync === 'true') {
@@ -894,11 +919,6 @@
 
       component.setting.delay = delay
       delay += 20
-
-      if (balMap.has(component.uuid)) {
-        component.setting.$hasSyncModule = true
-        balMap.set(component.uuid, component)
-      }
 
       return component
     })
diff --git a/src/tabviews/zshare/actionList/normalbutton/index.jsx b/src/tabviews/zshare/actionList/normalbutton/index.jsx
index d4f7524..bcf9a4f 100644
--- a/src/tabviews/zshare/actionList/normalbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/normalbutton/index.jsx
@@ -2320,7 +2320,7 @@
       Modal.success({
         title: msg,
         onOk: () => {
-          this.successContinue(sign, id)
+          this.successContinue(sign, id, res)
         }
       })
       return
@@ -2328,10 +2328,10 @@
 
     }
 
-    this.successContinue(sign, id)
+    this.successContinue(sign, id, res)
   }
 
-  successContinue = (sign, id) => {
+  successContinue = (sign, id, res) => {
     const { btn } = this.props
     const { btnconfig } = this.state
 
@@ -2452,6 +2452,16 @@
       } else {
         url = btn.verify.linkUrl
       }
+
+      if (/@/.test(url)) {
+        Object.keys(res).forEach(key => {
+          url = url.replace(new RegExp('@' + key + '@', 'ig'), res[key])
+        })
+      }
+      if (!/^http/.test(url)) {
+        url = window.location.origin + url
+      }
+
       window.open(url)
     }
   }
@@ -2586,9 +2596,9 @@
 
       if (verify.wxNoteLink === 'url' && verify.wxNoteLinkUrl) {
         _param.url = verify.wxNoteLinkUrl
-      } else if (verify.wxNoteLink === 'miniProgram' && window.GLOB.WXminiAppID) {
+      } else if (verify.wxNoteLink === 'miniProgram' && (window.GLOB.WXminiAppID || verify.wxNoteMiniId)) {
         _param.miniprogram = {
-          appid: window.GLOB.WXminiAppID,
+          appid: verify.wxNoteMiniId || window.GLOB.WXminiAppID,
           pagepath: '/pages/index/index'
         }
 
diff --git a/src/tabviews/zshare/mutilform/index.jsx b/src/tabviews/zshare/mutilform/index.jsx
index 1017e55..78f4aa6 100644
--- a/src/tabviews/zshare/mutilform/index.jsx
+++ b/src/tabviews/zshare/mutilform/index.jsx
@@ -476,6 +476,12 @@
             message: '璇烽�夋嫨' + item.label + '!'
           })
         }
+        if (['cascader', 'checkbox', 'checkcard', 'fileupload', 'multiselect'].includes(item.type) && item.fieldlength) {
+          item.rules.push({
+            max: item.fieldlength,
+            message: formRule.input.formMessage.replace('@max', item.fieldlength)
+          })
+        }
       }
 
       if (item.rules.length === 0) {
@@ -547,7 +553,7 @@
           item.subFields = []
           item.linkSubField.forEach(m => {
             let n = fieldMap.get(m)
-            if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
               item.subFields.push({
                 uuid: n.uuid,
                 field: m
@@ -570,7 +576,7 @@
           item.subFields = []
           item.linkSubField.forEach(m => {
             let n = fieldMap.get(m)
-            if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
               item.subFields.push({
                 uuid: n.uuid,
                 field: m
@@ -590,7 +596,7 @@
           item.subFields = []
           item.linkSubField.forEach(m => {
             let n = fieldMap.get(m)
-            if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
               item.subFields.push({
                 uuid: n.uuid,
                 field: m
@@ -602,7 +608,7 @@
           item.subFields = []
           item.linkSubField.forEach(m => {
             let n = fieldMap.get(m)
-            if (n && ['text', 'number', 'textarea'].includes(n.type)) {
+            if (n && ['text', 'number', 'textarea', 'select'].includes(n.type)) {
               item.subFields.push({
                 uuid: n.uuid,
                 field: m
diff --git a/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
index 30ef195..7b76860 100644
--- a/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
@@ -270,6 +270,14 @@
       })
     }
 
+    if (config.linkFields) {
+      config.linkFields.forEach((m, i) => {
+        setTimeout(() => {
+          MKEmitter.emit('mkFP', m.uuid, val, 0)
+        }, (i + 1) * 100)
+      })
+    }
+
     this.props.onChange(val, other)
     this.setState({value: val, showValue: ''}, () => {
       if (config.enter === 'tab') {
diff --git a/src/tabviews/zshare/mutilform/mkSelect/index.jsx b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
index 6f94b5d..c08ba6f 100644
--- a/src/tabviews/zshare/mutilform/mkSelect/index.jsx
+++ b/src/tabviews/zshare/mutilform/mkSelect/index.jsx
@@ -79,12 +79,15 @@
     MKEmitter.removeListener('mkFC', this.mkFormFocus)
   }
 
-  mkFormFocus = (type, uuid) => {
+  mkFormFocus = (type, uuid, val, level) => {
     if (uuid !== this.props.config.uuid) return
-    if (type !== 'focus') return
-
-    let _div = document.getElementById(uuid)
-    _div && _div.click && _div.click()
+    if (type === 'focus') {
+      let _div = document.getElementById(uuid)
+      _div && _div.click && _div.click()
+    } else if (type === 'input' && (!level || level < 10)) {
+      let _level = level || 1
+      this.selectChange(val, _level++)
+    }
   }
 
   mkFormHandle = (uuid, parentId, level) => {
@@ -123,7 +126,7 @@
     }
   }
 
-  selectChange = (val) => {
+  selectChange = (val, level) => {
     const { config } = this.state
     let other = {}
 
@@ -132,7 +135,7 @@
       option && config.subFields.forEach((n, i) => {
         other[n.field] = option[n.field]
         setTimeout(() => {
-          MKEmitter.emit('mkFC', 'input', n.uuid, option[n.field])
+          MKEmitter.emit('mkFC', 'input', n.uuid, option[n.field], level)
         }, i * 5)
       })
     }
@@ -177,7 +180,7 @@
           value={value}
           dropdownMatchSelectWidth={config.dropdown !== 'false'}
           filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-          onSelect={this.selectChange}
+          onSelect={(val) => this.selectChange(val)}
           onChange={(val) => val === undefined && this.selectChange('')}
           disabled={config.readonly}
         >
diff --git a/src/templates/modalconfig/dragelement/index.scss b/src/templates/modalconfig/dragelement/index.scss
index 742699b..e19cce3 100644
--- a/src/templates/modalconfig/dragelement/index.scss
+++ b/src/templates/modalconfig/dragelement/index.scss
@@ -128,12 +128,6 @@
       opacity: 0;
       z-index: 1;
     }
-    .ant-col-cuslabel {
-      width: 10.5%;
-    }
-    .ant-col-cuswrap {
-      width: 89.5%;
-    }
   }
   .ant-form-item label > .anticon {
     vertical-align: middle;
diff --git a/src/templates/modalconfig/index.jsx b/src/templates/modalconfig/index.jsx
index 3f2571f..cabfc7d 100644
--- a/src/templates/modalconfig/index.jsx
+++ b/src/templates/modalconfig/index.jsx
@@ -14,7 +14,6 @@
 import asyncComponent from '@/utils/asyncComponent'
 import { BaseConfig, SearchItems } from './source'
 import { updateForm } from '@/utils/utils-update.js'
-import MKEmitter from '@/utils/events.js'
 import './index.scss'
 
 const { Panel } = Collapse
@@ -124,7 +123,7 @@
 
   componentDidMount() {
     window.GLOB.formId = ''
-    MKEmitter.addListener('submitStyle', this.getStyle)
+
     document.onkeydown = (event) => {
       let e = event || window.event
       let keyCode = e.keyCode || e.which || e.charCode
@@ -157,7 +156,6 @@
    * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
    */
   componentWillUnmount () {
-    MKEmitter.removeListener('submitStyle', this.getStyle)
     this.setState = () => {
       return
     }
@@ -184,24 +182,6 @@
     }
 
     this.props.handleView(param)
-  }
-
-  getStyle = (comIds, style) => {
-    const { config } = this.state
-
-    if (comIds[0] !== 'form') return
-
-    let Index = config.fields.findIndex(n => n.uuid === comIds[1])
-
-    if (Index === -1) return
-    
-    let _config = fromJS(config).toJS()
-
-    _config.fields[Index].style = style
-
-    this.setState({
-      config: _config
-    })
   }
 
   /**
@@ -236,112 +216,21 @@
   handleForm = (_card) => {
     const { menu, tabConfig, subTabConfig } = this.props
     const { config } = this.state
+    
     let card = fromJS(_card).toJS()
-    let _inputfields = []
-    let _tabfields = []
-    let _linkableFields = []
-    let _linksupFields = []
-    let standardform = null
-    let index = null
-
-    config.fields.forEach((item, i) => {
-      if (card.uuid === item.uuid) {
-        index = i
-      }
-
-      if (!item.field || card.field === item.field) return
-
-      if (['text', 'number', 'textarea', 'color'].includes(item.type)) {
-        _inputfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-      if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
-        _tabfields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (['switch', 'check', 'popSelect'].includes(item.type)) {
-        _linksupFields.push({
-          field: item.field,
-          label: item.label
-        })
-      }
-
-      if (!['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) return
-
-      _linksupFields.push({
-        field: item.field,
-        label: item.label
-      })
-
-      if (item.type === 'multiselect' || (item.type === 'checkcard' && item.multiple === 'true')) return
-
-      _linkableFields.push({
-        field: item.field,
-        label: item.label + '-琛ㄥ崟'
-      })
-    })
-
-    if (index !== null) {
-      if (index === 0) {
-        standardform = config.fields[index + 1] || null
-      } else {
-        standardform = config.fields[index - 1] || null
-      }
-    }
-
-    let _fields = _linkableFields.map(cell => cell.field)
+    let columns = []
     if (subTabConfig) {
-      subTabConfig.columns.forEach(col => {
-        if (col.field && !_fields.includes(col.field)) {
-          _linkableFields.push({
-            field: col.field,
-            label: col.label + '-鏄剧ず鍒�'
-          })
-        }
-      })
+      columns = subTabConfig.columns
     } else if (tabConfig) {
-      tabConfig.columns.forEach(col => {
-        if (col.field && !_fields.includes(col.field)) {
-          _linkableFields.push({
-            field: col.field,
-            label: col.label + '-鏄剧ず鍒�'
-          })
-        }
-      })
+      columns = tabConfig.columns
     } else if (menu.LongParam) {
-      menu.LongParam.columns.forEach(col => {
-        if (col.field && !_fields.includes(col.field)) {
-          _linkableFields.push({
-            field: col.field,
-            label: col.label + '-鏄剧ず鍒�'
-          })
-        }
-      })
-    }
-
-    if (card.linkSubField && card.linkSubField.length > 0) {
-      let fields = _inputfields.map(item => item.field)
-      card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
-    }
-
-    if (!card.span && standardform && standardform.span) {
-      card.span = standardform.span
-      card.labelwidth = standardform.labelwidth
-    } else if (!card.span) {
-      card.span = 12
-      card.labelwidth = 33.3
+      columns = menu.LongParam.columns
     }
 
     this.setState({
-      standardform,
       visible: true,
       card: card,
-      formlist: getModalForm(card, _inputfields, _tabfields, _linkableFields, _linksupFields)
+      formlist: getModalForm(card, config.fields, columns)
     })
   }
 
@@ -772,7 +661,7 @@
             card={this.state.card}
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
-            standardform={this.state.standardform}
+            fields={config.fields}
             wrappedComponentRef={(inst) => this.formRef = inst}
           />
         </Modal>
diff --git a/src/templates/modalconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx
index 7baf400..9d141c3 100644
--- a/src/templates/modalconfig/settingform/index.jsx
+++ b/src/templates/modalconfig/settingform/index.jsx
@@ -25,25 +25,16 @@
     icon: this.props.config.setting.icon || '',
     appType: sessionStorage.getItem('appType'),
     viewType: sessionStorage.getItem('editMenuType') || '',
-    dialogInput: false
   }
 
   UNSAFE_componentWillMount () {
     const { config } = this.props
     const { appType, display } = this.state
     let fields = []
-    let dialogInput = null
 
     config.fields.forEach(f => {
       if (f.field && ['select', 'link', 'text', 'number', 'textarea'].includes(f.type) && f.hidden !== 'true' && f.readonly !== 'true') {
         fields.push(f)
-      }
-      if (f.field && f.hidden !== 'true' && f.readonly !== 'true') {
-        if (dialogInput === null) {
-          dialogInput = ['text', 'number'].includes(f.type)
-        } else {
-          dialogInput = false
-        }
       }
     })
 
@@ -56,8 +47,7 @@
 
     this.setState({
       fields: fields,
-      display: _display,
-      dialogInput
+      display: _display
     })
   }
 
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
index e63f73f..ab01815 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/customscript/index.jsx
@@ -81,7 +81,7 @@
   }
 
   handleConfirm = () => {
-    const { type, btn } = this.props
+    const { type, btn, workFlow } = this.props
     const { editItem, skip } = this.state
 
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
@@ -169,6 +169,18 @@
         let sql = this.state.verifySql + _initCustomScript + _prevCustomScript + _backCustomScript + tail
         sql = sql.replace(/@\$|\$@/ig, '').replace(/\$check@|@check\$/ig, '').replace(/@datam@/ig, `''`).replace(/@typename@/ig, `'debug'`)
         
+        if (workFlow === 'true') {
+          sql = sql.replace(/@works_flow_code@/ig, `'works_flow_code'`)
+          sql = sql.replace(/@works_flow_name@/ig, `'works_flow_name'`)
+          sql = sql.replace(/@works_flow_param@/ig, `'works_flow_param'`)
+          sql = sql.replace(/@works_flow_detail_id@/ig, `'works_flow_detail_id'`)
+          sql = sql.replace(/@status@/ig, `0`)
+          sql = sql.replace(/@statusname@/ig, `'寮�濮�'`)
+          sql = sql.replace(/@work_group@/ig, `'work_group'`)
+          sql = sql.replace(/@work_grade@/ig, '0')
+          sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
+        }
+
         if (skip) {
           this.setState({
             skip: false,
@@ -233,6 +245,24 @@
       database = database ? (database[0] || '') : ''
 
       _value = `Insert into ${database}${sheet} (${fields}createuserid,createuser,createstaff,bid)\nSelect ${fields}@userid@,@username,@fullname,@BID@ From #${sheet}`
+    } else if (value === 'flowSql') {
+      let sheet = btn.sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
+
+      _value = `insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+      select jskey,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+      from #${sheet}
+                                                                 
+      insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+      select jskey,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+      from #${sheet}
+                                                                 
+      insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+      select jskey,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
+      from #${sheet}
+                                                                 
+      insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
+      select jskey,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
+      from #${sheet}`
     } else {
       _value = value
     }
@@ -259,7 +289,7 @@
   }
 
   render() {
-    const { systemScripts, btn, type } = this.props
+    const { systemScripts, btn, type, workFlow } = this.props
     const { usefulfields, editItem, skip } = this.state
     const { getFieldDecorator } = this.props.form
     const formItemLayout = {
@@ -289,6 +319,7 @@
           {!type ? <Col span={24} className="sqlfield">
             <Form.Item label="鍙敤瀛楁">
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'鍏叡鍊硷紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�'}><span style={{color: '#1890ff'}}>BID, ID, LoginUID, SessionUid, UserID, Appkey, time_id, typename</span></Tooltip>,&nbsp;
+              {workFlow === 'true' ? <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title="宸ヤ綔娴佸彉閲忥紝璇锋寜鐓xxx@鏍煎紡浣跨敤銆�"><span style={{color: '#26C281'}}>works_flow_code, works_flow_name, works_flow_param, works_flow_detail_id, status, statusname, work_group, work_grade, start_type, </span></Tooltip> : null}
               <Tooltip mouseLeaveDelay={0.3} mouseEnterDelay={0.3} placement="top" title={'绯荤粺鍙橀噺锛岀郴缁熶細瀹氫箟鍙橀噺骞惰祴鍊笺��'}><span style={{color: '#fa8c16'}}>UserName, FullName, RoleID, mk_departmentcode, mk_organization, mk_user_type, mk_nation, mk_province, mk_city, mk_district, mk_address</span></Tooltip>,&nbsp;
               {usefulfields}
             </Form.Item>
@@ -319,9 +350,8 @@
                 onSelect={this.selectScript}
                 getPopupContainer={() => document.getElementById('verify-excelin-custom-scripts')}
               >
-                <Select.Option key="default" value={'default'}>
-                  榛樿sql
-                </Select.Option>
+                <Select.Option key="default" value="default">榛樿sql</Select.Option>
+                {workFlow === 'true' ? <Select.Option key="flow" value="flowSql">榛樿sql锛堝伐浣滄祦锛�</Select.Option> : null}
                 <Select.Option key="debugger" value={`z_debug: select @ErrorCode='E',@retmsg='娴嬭瘯鏂偣' goto aaa`}>
                   娴嬭瘯鏂偣
                 </Select.Option>
diff --git a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
index c58226f..be7041f 100644
--- a/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/verifyexcelin/index.jsx
@@ -205,6 +205,89 @@
             </div>
           )
       },
+      {
+        dataIndex: 'sqlRender',
+        render: (record) => {
+          let columns = this.state.verify.columns
+
+          let textFields = []
+          let numberFields = []
+          let dateFields = []
+          columns.forEach((col) => {
+            if (/Nvarchar/ig.test(col.type)) {
+              textFields.push(col.Column)
+            } else if (/Decimal|int/ig.test(col.type)) {
+              numberFields.push(col.Column)
+            } else if (/date/ig.test(col.type)) {
+              dateFields.push(col.Column)
+            }
+          })
+
+          let _fields = record.field.split(',')
+          let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
+          _fields_ = _fields_.join(' and ')
+
+          let _where = []
+          _fields.forEach(f => {
+            if (textFields.includes(f)) {
+              _where.push(`${f}!=''`)
+            } else if (numberFields.includes(f)) {
+              _where.push(`${f}!=0`)
+            } else if (dateFields.includes(f)) {
+              _where.push(`${f}>'1949-10-01'`)
+            }
+          })
+          _where = _where.length ? `where ${_where.join(' and ')} ` : ''
+
+          if (record.verifyType === 'logic' || record.verifyType === 'logic_temp') {
+            _fields_ += ' and b.deleted=0'
+          }
+
+          let _afields = []
+          _fields = _fields.map(f => {
+            if (numberFields.includes(f)) {
+              _afields.push(`cast(a.${f} as nvarchar(50))`)
+              return `cast(${f} as nvarchar(50))`
+            } else if (dateFields.includes(f)) {
+              _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+              return `CONVERT(nvarchar(50), ${f}, 21)`
+            }
+            _afields.push(`a.${f}`)
+
+            return f
+          })
+
+          let _sheet = this.props.card.sheet
+
+          let database = _sheet.match(/(.*)\.(.*)\.|@db@/ig) || ''
+          let sheet = _sheet.replace(/(.*)\.(.*)\.|@db@/ig, '')
+          
+          database = database ? (database[0] || '') : ''
+
+          let sql = `
+          /* 閲嶅鎬ч獙璇� */
+          Set @tbid=''
+          Select top 1 @tbid=${_fields.join('+\' \'+')} from (select 1 as n,${record.field} from #${sheet} ${_where}) a group by ${record.field} having sum(n)>1
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${record.errorCode}',@retmsg=@tbid+' 閲嶅'
+            goto aaa
+          end
+          
+          ${record.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
+          Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${database}${sheet} b on ${_fields_}
+          
+          If @tbid!=''
+          Begin
+            select @ErrorCode='${record.errorCode}',@retmsg=@tbid+' 涓庡凡鏈夋暟鎹噸澶�'
+            goto aaa
+          end` : ''}
+          `
+          
+          return sql.split(/\n\s{10}/ig).map(n => n.replace(/^\s{2}/ig, '&nbsp;&nbsp;'))
+        }
+      }
     ],
     scriptsColumns: [
       {
@@ -316,6 +399,16 @@
     _verify.columns = _columns
     _verify.scripts = _verify.scripts || []
     _verify.uniques = _verify.uniques || []
+
+    if (window.GLOB.process && card.intertype === 'system') {
+      _verify.workFlow = _verify.workFlow || 'false'
+      _verify.flowType = 'start'
+      _verify.flowSql = _verify.flowSql || 'true'
+    } else {
+      delete _verify.workFlow
+      delete _verify.flowType
+      delete _verify.flowSql
+    }
 
     this.setState({
       searchKey: '',
@@ -792,21 +885,11 @@
     })
   }
 
-  onOptionChange = (e) => {
+  onOptionChange = (value, key) => {
     const { verify } = this.state
-    let value = e.target.value
 
     this.setState({
-      verify: {...verify, default: value}
-    })
-  }
-
-  onHandleChange = (e) => {
-    const { verify } = this.state
-    let value = e.target.value
-
-    this.setState({
-      verify: {...verify, excelHandle: value}
+      verify: {...verify, [key]: value}
     })
   }
 
@@ -888,8 +971,8 @@
             <Form {...formItemLayout}>
               <Row gutter={24}>
                 {card.intertype === 'system' ? <Col span={8}>
-                  <Form.Item label={'榛樿sql'}>
-                    <Radio.Group value={verify.default} onChange={this.onOptionChange}>
+                  <Form.Item label="榛樿sql">
+                    <Radio.Group value={verify.default} onChange={(e) => this.onOptionChange(e.target.value, 'default')}>
                       <Radio value="true">鎵ц</Radio>
                       <Radio value="false">涓嶆墽琛�</Radio>
                     </Radio.Group>
@@ -905,7 +988,7 @@
                     {getFieldDecorator('excelHandle', {
                       initialValue: verify.excelHandle
                     })(
-                    <Radio.Group onChange={this.onHandleChange}>
+                    <Radio.Group onChange={(e) => this.onOptionChange(e.target.value, 'excelHandle')}>
                       <Radio value="false">榛樿</Radio>
                       <Radio value="true">鑷畾涔�</Radio>
                     </Radio.Group>)}
@@ -954,6 +1037,27 @@
                     })(<CodeMirror mode="text/javascript" theme="cobalt" />)}
                   </Form.Item>
                 </Col> : null}
+                {window.GLOB.process && card.intertype === 'system' ? <Col span={8}>
+                  <Form.Item label={
+                    <Tooltip placement="bottomLeft" title="瀵煎叆Excel宸ヤ綔娴佷粎鏀寔鍙戣捣娴佺▼銆�">
+                      <QuestionCircleOutlined className="mk-form-tip" />
+                      宸ヤ綔娴�
+                    </Tooltip>
+                  }>
+                    <Radio.Group value={verify.workFlow} onChange={(e) => {this.onOptionChange(e.target.value, 'workFlow')}}>
+                      <Radio value="true">寮�鍚�</Radio>
+                      <Radio value="false">涓嶅紑鍚�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col> : null}
+                {verify.workFlow === 'true' ? <Col span={8}>
+                  <Form.Item label="榛樿sql锛堝伐浣滄祦锛�">
+                    <Radio.Group value={verify.flowSql} onChange={(e) => {this.onOptionChange(e.target.value, 'flowSql')}}>
+                      <Radio value="true">鎵ц</Radio>
+                      <Radio value="false">涓嶆墽琛�</Radio>
+                    </Radio.Group>
+                  </Form.Item>
+                </Col> : null}
               </Row>
             </Form>
           </TabPane>
@@ -980,7 +1084,7 @@
             </span>
           } key="unique">
             <UniqueForm fields={verify.columns} uniqueChange={this.uniqueChange}/>
-            <EditTable actions={['edit', 'move', 'del', 'status']} data={verify.uniques} columns={uniqueColumns} onChange={this.changeUniques}/>
+            <EditTable actions={['edit', 'move', 'del', 'status', 'sql']} data={verify.uniques} columns={uniqueColumns} onChange={this.changeUniques}/>
           </TabPane> : null}
           {card.intertype === 'system' ? <TabPane tab={
             <span>
@@ -1000,6 +1104,7 @@
                 btn={this.props.card}
                 usefulfields={verify.columns}
                 scripts={verify.scripts}
+                workFlow={verify.workFlow}
                 systemScripts={this.state.systemScripts}
                 scriptsChange={this.scriptsChange}
                 wrappedComponentRef={(inst) => this.scriptsFullForm = inst}
@@ -1009,6 +1114,7 @@
               btn={this.props.card}
               usefulfields={verify.columns}
               scripts={verify.scripts}
+              workFlow={verify.workFlow}
               systemScripts={this.state.systemScripts}
               scriptsChange={this.scriptsChange}
               wrappedComponentRef={(inst) => this.scriptsForm = inst}
diff --git a/src/templates/zshare/editTable/index.jsx b/src/templates/zshare/editTable/index.jsx
index fcc5e6d..9ce9e95 100644
--- a/src/templates/zshare/editTable/index.jsx
+++ b/src/templates/zshare/editTable/index.jsx
@@ -366,7 +366,7 @@
     if (list) {
       Modal.info({
         title: '',
-        width: 500,
+        width: 700,
         className: 'sql-example',
         icon: null,
         content: list.map((n, index) => <div key={index} dangerouslySetInnerHTML={{ __html: n }}></div>)
@@ -828,7 +828,7 @@
     
     let  columns = this.state.columns.map(col => {
       if (col.copy) {
-        col.render = (text) => (<Paragraph copyable>{text}</Paragraph>)
+        col.render = (text, record) => (<Paragraph copyable={{ text: text, onCopy: () => this.setState({editLineId: record.uuid}) }}>{text}</Paragraph>)
       }
 
       if (!col.editable) return col
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 50071ac..621dd29 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -731,13 +731,8 @@
 
 /**
  * @description 鑾峰彇琛ㄥ崟閰嶇疆淇℃伅
- * @param {*} card            // 琛ㄥ崟瀵硅薄
- * @param {*} inputfields     // 鍙啓鍏ヨ〃鍗�
- * @param {*} tabfields       // 鍙垏鎹㈣〃鍗�
- * @param {*} linkableFields  // 鍙叧鑱旇〃鍗�
- * @param {*} linksupFields   // 涓婄骇琛ㄥ崟
  */
-export function getModalForm (card, inputfields = [], tabfields = [], linkableFields, linksupFields, columns = []) {
+export function getModalForm (card, fields, columns = []) {
   let appType = sessionStorage.getItem('appType')
   let roleList = sessionStorage.getItem('sysRoles')
   if (roleList) {
@@ -774,6 +769,64 @@
     msgTemps = []
   }
 
+  let inputfields = []
+  let tabfields = []
+  let linkableFields = []
+  let linksupFields = []
+
+  fields.forEach(item => {
+    if (!item.field || card.field === item.field) return
+
+    if (['text', 'number', 'textarea', 'select'].includes(item.type)) {
+      inputfields.push({
+        field: item.field,
+        label: item.label
+      })
+    }
+    if (item.hidden !== 'true' && ['text', 'number', 'select', 'link'].includes(item.type)) {
+      tabfields.push({
+        field: item.field,
+        label: item.label
+      })
+    }
+
+    if (['switch', 'check', 'popSelect'].includes(item.type)) {
+      linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+    }
+    
+    if (['select', 'link', 'radio', 'checkcard', 'multiselect'].includes(item.type)) {
+      linksupFields.push({
+        field: item.field,
+        label: item.label
+      })
+    }
+
+    if (['select', 'link', 'radio', 'popSelect'].includes(item.type) || (item.type === 'checkcard' && item.multiple !== 'true')) {
+      linkableFields.push({
+        field: item.field,
+        label: item.label + '-琛ㄥ崟'
+      })
+    }
+  })
+
+  let _fields = linkableFields.map(cell => cell.field)
+  columns.forEach(col => {
+    if (col.field && !_fields.includes(col.field)) {
+      linkableFields.push({
+        field: col.field,
+        label: col.label + '-鏄剧ず鍒�'
+      })
+    }
+  })
+
+  if (card.linkSubField && card.linkSubField.length > 0) {
+    let fields = inputfields.map(item => item.field)
+    card.linkSubField = card.linkSubField.filter(item => fields.includes(item))
+  }
+
   inputfields = inputfields.map((item, index) => {
     item.label = `${index + 1}銆�${item.field || ''}锛�${item.label}锛塦
     return item
diff --git a/src/templates/zshare/modalform/index.jsx b/src/templates/zshare/modalform/index.jsx
index 17b3585..7b515e6 100644
--- a/src/templates/zshare/modalform/index.jsx
+++ b/src/templates/zshare/modalform/index.jsx
@@ -51,7 +51,7 @@
 class MainSearch extends Component {
   static propTpyes = {
     formlist: PropTypes.any,
-    standardform: PropTypes.any,
+    fields: PropTypes.array,
     card: PropTypes.object,
     inputSubmit: PropTypes.any
   }
@@ -537,18 +537,21 @@
   changeVal = (val, type) => {
     if (type !== 'span' || ![24, 12, 8, 6].includes(val)) return
 
-    const { standardform } = this.props
+    const { card, fields } = this.props
 
-    if (!standardform || ![24, 12, 8, 6].includes(standardform.span) || !standardform.labelwidth) return
+    let index = fields.findIndex(item => card.uuid === item.uuid)
+    let stform = fields[index - 1]
+    
+    if (!stform || ![24, 12, 8, 6].includes(stform.span) || !stform.labelwidth) return
 
     let labelwidth = null
 
-    if (standardform.span === val) {
-      labelwidth = standardform.labelwidth
-    } else if (standardform.span > val) {
+    if (stform.span === val) {
+      labelwidth = stform.labelwidth
+    } else if (stform.span > val) {
       labelwidth = 33.3
     } else {
-      switch(standardform.span) {
+      switch(stform.span) {
         case 12:
           labelwidth = 16.2
           break;
@@ -930,8 +933,8 @@
     }
   }
 
-  handleConfirm = (fields) => {
-    const { card } = this.props
+  handleConfirm = () => {
+    const { card, fields } = this.props
     // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
     return new Promise((resolve, reject) => {
       this.props.form.validateFieldsAndScroll((err, values) => {
diff --git a/src/templates/zshare/verifycard/baseform/index.jsx b/src/templates/zshare/verifycard/baseform/index.jsx
index affd4f5..d67515e 100644
--- a/src/templates/zshare/verifycard/baseform/index.jsx
+++ b/src/templates/zshare/verifycard/baseform/index.jsx
@@ -159,37 +159,38 @@
     let _verify = {...verify, [key]: value}
 
     if (_verify.noteEnable !== 'true') {
-      _verify.noteCode = ''
-      _verify.noteId = ''
+      delete _verify.noteCode
+      delete _verify.noteId
     }
     if (_verify.emailEnable !== 'true') {
-      _verify.emailCode = ''
-      _verify.emailId = ''
+      delete _verify.emailCode
+      delete _verify.emailId
     }
     if (_verify.printEnable !== 'true') {
-      _verify.printTempId = ''
+      delete _verify.printTempId
     }
     if (_verify.linkEnable !== 'true') {
       delete _verify.linkUrl
       delete _verify.linkProUrl
     }
     if (_verify.accountdate !== 'true') {
-      _verify.accountfield = ''
-      _verify.voucherdate = ''
+      delete _verify.accountfield
+      delete _verify.voucherdate
     }
     if (_verify.preHandle !== 'true') {
-      _verify.pre_func = ''
+      delete _verify.pre_func
     }
     if (_verify.wxNote !== 'true') {
-      _verify.wxTemplateId = ''
-      _verify.wxNoteLink = ''
-      _verify.wxNoteLinkUrl = ''
-      _verify.wxNoteLinkMenuId = ''
-      _verify.wxNoteCallback = 'false'
-      _verify.wxNoteKeys = null
-
+      delete _verify.wxTemplateId
+      delete _verify.wxNoteLink
+      delete _verify.wxNoteLinkUrl
+      delete _verify.wxNoteMiniId
+      delete _verify.wxNoteLinkMenuId
+      delete _verify.wxNoteCallback
       delete _verify.wxCustomTempId
 
+      _verify.wxNoteKeys = null
+      
       if (this.state.selectTemp) {
         this.setState({selectTemp: null})
       }
@@ -342,12 +343,7 @@
       <Form {...formItemLayout}>
         <Row gutter={24}>
           {card.sqlType !== 'custom' && card.intertype !== 'inner' ? <Col span={8}>
-            <Form.Item label={
-              <Tooltip placement="bottomLeft" title={'榛樿sql鎵ц椤哄簭涓鸿嚜瀹氫箟鑴氭湰涔嬪墠'}>
-                <QuestionCircleOutlined className="mk-form-tip" />
-                榛樿sql
-              </Tooltip>
-            }>
+            <Form.Item label="榛樿sql">
               <Radio.Group value={verify.default} onChange={(e) => {this.onOptionChange(e.target.value, 'default')}}>
                 <Radio value="true">鎵ц</Radio>
                 <Radio value="false">涓嶆墽琛�</Radio>
@@ -548,7 +544,7 @@
           <Col span={24}></Col>
           <Col span={8}>
             <Form.Item label={
-              <Tooltip placement="bottomLeft" title="鎸夐挳鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勯摼鎺ュ湴鍧�銆�">
+              <Tooltip placement="bottomLeft" overlayStyle={{maxWidth: 350}} title="鎸夐挳鎵ц鎴愬姛鍚庨渶瑕佹墦寮�鐨勯摼鎺ュ湴鍧�銆傚鏋滃湴鍧�涓嶆槸http寮�濮嬶紝浼氭嫾鎺ュ綋鍓嶇郴缁熷煙鍚嶏紝渚嬪锛氬湴鍧�涓� /xxxx 鏃讹紝浼氭墦寮� http://***.***.**/xxxx銆�">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鎵撳紑閾炬帴
               </Tooltip>
@@ -696,6 +692,16 @@
           </Col> : null}
           {verify.wxNoteLink === 'miniProgram' ? <Col span={8}>
             <Form.Item label={
+              <Tooltip placement="top" title="鍙寚瀹氳烦杞皬绋嬪簭鐨処D锛屾湭璁剧疆鏃堕粯璁や娇鐢ㄩ厤缃枃浠朵腑鐨勫皬绋嬪簭ID銆�">
+                <QuestionCircleOutlined className="mk-form-tip" />
+                灏忕▼搴廔D
+              </Tooltip>
+            }>
+              <Input placeholder="" autoComplete="off" value={verify.wxNoteMiniId || ''} onChange={(e) => {this.onOptionChange(e.target.value, 'wxNoteMiniId')}}/>
+            </Form.Item>
+          </Col> : null}
+          {verify.wxNoteLink === 'miniProgram' ? <Col span={8}>
+            <Form.Item label={
               <Tooltip placement="top" title="娣诲姞鑿滃崟ID鍙烦杞嚦灏忕▼搴忔寚瀹氶〉闈紝绌哄�奸粯璁よ烦杞嚦灏忕▼搴忛椤点�傛敞锛氭暟鎹噷涓鏋滄湁bid瀛楁锛堝�间笉涓虹┖锛夛紝鎵撳紑灏忕▼搴忔椂浼氬仛涓築ID浼犲叆椤甸潰涓��">
                 <QuestionCircleOutlined className="mk-form-tip" />
                 鑿滃崟ID
diff --git a/src/templates/zshare/verifycard/index.jsx b/src/templates/zshare/verifycard/index.jsx
index 8bc3126..9e50ea7 100644
--- a/src/templates/zshare/verifycard/index.jsx
+++ b/src/templates/zshare/verifycard/index.jsx
@@ -86,7 +86,7 @@
         title: '楠岃瘉绫诲瀷',
         dataIndex: 'verifyType',
         width: '14%',
-        render: (text, record) => record.verifyType === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉',
+        render: (text) => text === 'logic' ? '閫昏緫楠岃瘉' : '鐗╃悊楠岃瘉',
         inputType: 'select',
         editable: true,
         options: [
@@ -124,7 +124,7 @@
 
           record.field.split(',').forEach((_field, index) => {
             let _key = _field.toLowerCase()
-            _fieldValue.push(`${_key}=${_key === 'bid' ? '@BID@' : ''}`)
+            _fieldValue.push(`${_key}=${_key === 'bid' ? '@BID@' : `''`}`)
             _value.push(`${_labels[index] || ''}锛歺xx`)
           })
 
@@ -641,8 +641,6 @@
     _verify.uniques = _verify.uniques || []
     _verify.contrasts = _verify.contrasts || []
     _verify.accountdate = _verify.accountdate || 'false'
-    _verify.accountfield = _verify.accountfield || ''
-    _verify.voucherdate = _verify.voucherdate || ''
     _verify.customverifys = _verify.customverifys || []
     _verify.billcodes = _verify.billcodes || []
     _verify.voucher = _verify.voucher || {enabled: false}
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index 841817d..d49eb33 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -364,80 +364,6 @@
   }
 
   /**
-   * @description 鑾峰彇鍙叧鑱旀ā鍧�
-   */
-  static getLinkModules (components) {
-    let modules = components.map(item => {
-      if ((item.type === 'card' && item.subtype === 'datacard') || (item.type === 'table' && item.subtype === 'normaltable')) {
-        return {
-          value: item.uuid,
-          label: item.name
-        }
-      } else if (item.type === 'tabs') {
-        let _item = {
-          value: item.uuid,
-          label: item.name,
-          children: item.subtabs.map(f_tab => {
-            let subItem = {
-              value: f_tab.uuid,
-              label: f_tab.label,
-              children: this.getLinkModules(f_tab.components)
-            }
-
-            if (!subItem.children || subItem.children.length === 0) {
-              return {children: null}
-            }
-            return subItem
-          })
-        }
-
-        _item.children = _item.children.filter(t => t.children !== null)
-
-        if (_item.children.length === 0) {
-          return {children: null}
-        }
-
-        return _item
-      } else if (item.type === 'group') {
-        let _item = {
-          value: item.uuid,
-          label: item.name,
-          children: item.components.map(f_tab => {
-            if ((f_tab.type === 'card' && f_tab.subtype === 'datacard') || (f_tab.type === 'table' && f_tab.subtype === 'normaltable')) {
-              return {
-                value: f_tab.uuid,
-                label: f_tab.name
-              }
-            }
-            return {
-              children: null
-            }
-          })
-        }
-
-        _item.children = _item.children.filter(t => t.children !== null)
-
-        if (_item.children.length === 0) {
-          return {children: null}
-        }
-
-        return _item
-      } else {
-        return {
-          children: null
-        }
-      }
-    })
-
-    modules = modules.filter(mod => mod.children !== null)
-
-    if (modules.length === 0) {
-      return null
-    }
-    return modules
-  }
-
-  /**
    * @description 鐢熸垚32浣島uid string + 鏃堕棿
    * @return {String}  uuid
    */
@@ -1014,6 +940,128 @@
 }
 
 /**
+ * @description 鑾峰彇鍙叧鑱旀ā鍧�
+ */
+export function getLinkModules (components) {
+  let modules = components.map(item => {
+    if ((item.type === 'card' && item.subtype === 'datacard') || (item.type === 'table' && item.subtype === 'normaltable')) {
+      return {
+        value: item.uuid,
+        label: item.name
+      }
+    } else if (item.type === 'tabs') {
+      let _item = {
+        value: item.uuid,
+        label: item.name,
+        children: item.subtabs.map(f_tab => {
+          let subItem = {
+            value: f_tab.uuid,
+            label: f_tab.label,
+            children: getLinkModules(f_tab.components)
+          }
+
+          if (!subItem.children || subItem.children.length === 0) {
+            return {children: null}
+          }
+          return subItem
+        })
+      }
+
+      _item.children = _item.children.filter(t => t.children !== null)
+
+      if (_item.children.length === 0) {
+        return {children: null}
+      }
+
+      return _item
+    } else if (item.type === 'group') {
+      let _item = {
+        value: item.uuid,
+        label: item.name,
+        children: item.components.map(f_tab => {
+          if ((f_tab.type === 'card' && f_tab.subtype === 'datacard') || (f_tab.type === 'table' && f_tab.subtype === 'normaltable')) {
+            return {
+              value: f_tab.uuid,
+              label: f_tab.name
+            }
+          }
+          return {
+            children: null
+          }
+        })
+      }
+
+      _item.children = _item.children.filter(t => t.children !== null)
+
+      if (_item.children.length === 0) {
+        return {children: null}
+      }
+
+      return _item
+    } else {
+      return {
+        children: null
+      }
+    }
+  })
+
+  modules = modules.filter(mod => mod.children !== null)
+
+  if (modules.length === 0) {
+    return null
+  }
+  return modules
+}
+
+/**
+ * @description 鑾峰彇鍏叡鏁版嵁婧�
+ */
+export function getInterfaces () {
+  let menu = window.GLOB.customMenu
+
+  let interfaces = []
+  if (menu.interfaces) {
+    menu.interfaces.forEach(item => {
+      if (item.status === 'true') {
+        interfaces.push({
+          value: item.uuid,
+          label: item.name,
+          columns: JSON.parse(JSON.stringify(item.columns))
+        })
+      }
+    })
+  }
+
+  let mapComponents = (components = []) => {
+    components.forEach(item => {
+      if (item.type === 'card' && item.subtype === 'datacard') {
+        interfaces.push({
+          value: item.uuid,
+          label: item.name + '锛堟暟鎹崱锛�',
+          columns: JSON.parse(JSON.stringify(item.columns))
+        })
+      } else if (item.type === 'table' && item.subtype === 'normaltable') {
+        interfaces.push({
+          value: item.uuid,
+          label: item.name + '锛堝父鐢ㄨ〃锛�',
+          columns: JSON.parse(JSON.stringify(item.columns))
+        })
+      } else if (item.type === 'tabs') {
+        item.subtabs.forEach(f_tab => {
+          mapComponents(f_tab.components)
+        })
+      } else if (item.type === 'group') {
+        mapComponents(item.components)
+      }
+    })
+  }
+
+  mapComponents(menu.components)
+
+  return interfaces
+}
+
+/**
  * @description 鏍煎紡鍖栨悳绱㈡潯浠�
  */
 export function formatSearch (searches) {
diff --git a/src/utils/utils.js b/src/utils/utils.js
index be865dc..1fa8b28 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -1048,12 +1048,18 @@
           }
         } else if (typeof(val) === 'string') {
           val = val.replace(/(^\s+$)|\t+|\v+/ig, '')
-          if (!val && col.required === 'true') {           // 鏃堕棿蹇呭~鏍¢獙
-            errors.push(_position + '鍐呭涓嶅彲涓虹┖')
-          } else if (val && !/^[1-9][0-9]{3}/.test(val)) { // 鏃堕棿姝e垯鏍¢獙
+          if (!val) {
+            if (col.required === 'true') {         // 鏃堕棿蹇呭~鏍¢獙
+              errors.push(_position + '鍐呭涓嶅彲涓虹┖')
+            } else if (col.type === 'date') {
+              val = '1949-10-01'
+            } else if (col.type === 'datetime') {
+              val = '1949-10-01 00:00:00'
+            }
+          } else if (!/^[1-9][0-9]{3}/.test(val)) { // 鏃堕棿姝e垯鏍¢獙
             errors.push(_position + '鏃堕棿鏍煎紡閿欒')
           }
-        } else {                                           // 鏃堕棿鏍煎紡閿欒
+        } else {                                    // 鏃堕棿鏍煎紡閿欒
           errors.push(_position + '鏃堕棿鏍煎紡閿欒')
         }
       }
@@ -1128,9 +1134,15 @@
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
       let textFields = []
+      let numberFields = []
+      let dateFields = []
       btn.columns.forEach((col) => {
-        if (/^Nvarchar/ig.test(col.type)) {
+        if (/Nvarchar/ig.test(col.type)) {
           textFields.push(col.Column)
+        } else if (/Decimal|int/ig.test(col.type)) {
+          numberFields.push(col.Column)
+        } else if (/date/ig.test(col.type)) {
+          dateFields.push(col.Column)
         }
       })
 
@@ -1139,13 +1151,17 @@
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
-        let _afields = _fields.map(_field => `a.${_field}`)
+        
         _fields_ = _fields_.join(' and ')
 
         let _where = []
         _fields.forEach(f => {
           if (textFields.includes(f)) {
             _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
           }
         })
         _where = _where.length ? `where ${_where.join(' and ')} ` : ''
@@ -1153,6 +1169,20 @@
         if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
 
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
@@ -1226,12 +1256,84 @@
 
       ${_uniquesql}
       ${_prevCustomScript}
-      ${_insert}
+      ${_insert}`
+
+    if (item.$process && btn.workFlow === 'true' && window.GLOB.UserCacheMap.has(item.$flowId)) {
+      let flow = window.GLOB.UserCacheMap.get(item.$flowId)
+      let target = flow.cells.filter(cell => cell.mknode === 'start')[0]
+      
+      let flowsql = ''
+      let status = 0
+      let statusName = ''
+      let detailId = ''
+      let work_grade = sessionStorage.getItem('work_grade') || 0
+  
+      if (target) {
+        detailId = target.id
+        status = target.mkdata.status
+        statusName = target.mkdata.statusName
+      }
+  
+      if (!target) {
+        status = 0
+        statusName = '寮傚父'
+  
+        flowsql = `
+        /* 宸ヤ綔娴佸紓甯竤ql */
+        select @ErrorCode='E',@retmsg='宸ヤ綔娴佹棤寮�濮嬭妭鐐�' goto aaa
+        `
+      } else if (btn.flowSql === 'true') {
+        flowsql = `
+        /* 宸ヤ綔娴侀粯璁ql */
+        insert into s_my_works_flow (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,work_group,works_flow_detail_id,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@,@works_flow_param@,@status@,@statusname@,@work_group@,@works_flow_detail_id@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_log (works_flow_id,works_flow_code,works_flow_name,works_flow_param,status,statusname,works_flow_detail_id,work_group,work_grade,bid,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_name@ ,@works_flow_param@,@status@,@statusname@,@works_flow_detail_id@,@work_group@,@work_grade@,@bid@,@UserID@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_notice (works_flow_id,works_flow_code,works_flow_detail_id,userid,notice_type,createuserid,CreateUser,CreateStaff,upid)
+        select jskey,@works_flow_code@,@works_flow_detail_id@,@userid@,@start_type@,@userid@,@UserName,@FullName,@time_id@
+        from #${sheet}
+                                                                   
+        insert into s_my_works_flow_role (works_flow_id,works_flow_code,userid,works_flow_detail_id,createuserid,CreateUser,CreateStaff,upid,typecharone)
+        select jskey,@works_flow_code@,@userid@,@works_flow_detail_id@,@userid@,@UserName,@FullName,@time_id@,'begin'
+        from #${sheet}
+        `
+      }
+      sql += `
+      ${flowsql}
       ${_backCustomScript}
 
       drop table #${sheet}
       
       aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+
+      sql = sql.replace(/@start_type@/ig, `'寮�濮�'`)
+      sql = sql.replace(/@works_flow_code@/ig, `'${flow.flow_code}'`)
+      sql = sql.replace(/@works_flow_name@/ig, `'${flow.flow_name}'`)
+  
+      if (target) {
+        let label = target.attrs && target.attrs.text && target.attrs.text.text ? target.attrs.text.text : ''
+        let msg = {...target.mkdata, label: label, id: target.id, checkIds: [], checkUsers: []}
+        sql = sql.replace(/@works_flow_param@/ig, `'${window.btoa(window.encodeURIComponent(JSON.stringify(msg)))}'`)
+      } else {
+        sql = sql.replace(/@works_flow_param@/ig, `''`)
+      }
+      sql = sql.replace(/@works_flow_detail_id@/ig, `'${detailId}'`)
+      sql = sql.replace(/@status@/ig, `'${status}'`)
+      sql = sql.replace(/@statusname@/ig, `'${statusName}'`)
+      sql = sql.replace(/@work_group@/ig, `'${sessionStorage.getItem('work_group') || ''}'`)
+      sql = sql.replace(/@work_grade@/ig, `'${work_grade}'`)
+    } else {
+      sql += `
+      ${_backCustomScript}
+
+      drop table #${sheet}
+      
+      aaa: select @ErrorCode as ErrorCode,@retmsg as retmsg`
+    }
 
     sql = sql.replace(/\n\s{6}/ig, '\n')
 
@@ -1362,17 +1464,54 @@
 
     let _uniquesql = ''
     if (btn.uniques && btn.uniques.length > 0) {
+      let textFields = []
+      let numberFields = []
+      let dateFields = []
+      columns.forEach((col) => {
+        if (/Nvarchar/ig.test(col.datatype)) {
+          textFields.push(col.field)
+        } else if (/Decimal|int/ig.test(col.datatype)) {
+          numberFields.push(col.field)
+        } else if (/date/ig.test(col.datatype)) {
+          dateFields.push(col.field)
+        }
+      })
       btn.uniques.forEach(unique => {
         if (unique.status === 'false' || !unique.verifyType) return
 
         let _fields = unique.field.split(',')
         let _fields_ = _fields.map(_field => `a.${_field}=b.${_field}`)
-        let _afields = _fields.map(_field => `a.${_field}`)
         _fields_ = _fields_.join(' and ')
+
+        let _where = []
+        _fields.forEach(f => {
+          if (textFields.includes(f)) {
+            _where.push(`${f}!=''`)
+          } else if (numberFields.includes(f)) {
+            _where.push(`${f}!=0`)
+          } else if (dateFields.includes(f)) {
+            _where.push(`${f}>'1949-10-01'`)
+          }
+        })
+        _where = _where.length ? `where ${_where.join(' and ')} ` : ''
 
         if (unique.verifyType === 'logic' || unique.verifyType === 'logic_temp') {
           _fields_ += ' and b.deleted=0'
         }
+
+        let _afields = []
+        _fields = _fields.map(f => {
+          if (numberFields.includes(f)) {
+            _afields.push(`cast(a.${f} as nvarchar(50))`)
+            return `cast(${f} as nvarchar(50))`
+          } else if (dateFields.includes(f)) {
+            _afields.push(`CONVERT(nvarchar(50), a.${f}, 21)`)
+            return `CONVERT(nvarchar(50), ${f}, 21)`
+          }
+          _afields.push(`a.${f}`)
+
+          return f
+        })
 
         _uniquesql += `
       /* 閲嶅鎬ч獙璇� */
@@ -1386,7 +1525,7 @@
       end
       
       ${unique.verifyType.indexOf('temp') === -1 ? `Set @tbid=''
-      Select top 1 @tbid=${_afields.join('+\' \'+')} from  #${sheet} a Inner join ${database}${sheet} b on ${_fields_}
+      Select top 1 @tbid=${_afields.join('+\' \'+')} from ${_where ? `(select * from #${sheet} ${_where})` : `#${sheet}`} a Inner join ${database}${sheet} b on ${_fields_}
       
       If @tbid!=''
       Begin
@@ -1867,7 +2006,7 @@
         if (_key === 'bid' && !_val) { // 琛ㄥ崟涓病鏈塨id鍒欎娇鐢ㄧ郴缁焍id鍙橀噺
           _val = BID
         }
-        
+
         _fieldValue.push(`${_key}='${_val}'`)
         _value.push(`${_labels[index] || ''}锛�${_val || ''}`)
       })
diff --git a/src/views/login/index.jsx b/src/views/login/index.jsx
index c2fa81c..d8a5ada 100644
--- a/src/views/login/index.jsx
+++ b/src/views/login/index.jsx
@@ -464,6 +464,16 @@
             }
             box = box.join(',')
             localStorage.setItem(_authUrl, box)
+
+            if (res.e_files === 'true') {
+              localStorage.setItem(_href + 'files', md5(_href + 'files'))
+              localStorage.setItem(_href + 'filesDate', res.e_files_end_date)
+              window.GLOB.storeFiles = true
+              window.GLOB.storeDate = Math.ceil((new Date(res.e_files_end_date).getTime() - new Date().getTime()) / 86400000)
+            } else {
+              localStorage.removeItem(_href + 'files')
+              window.GLOB.storeFiles = false
+            }
     
             this.setState({
               auth: true
@@ -477,6 +487,9 @@
             }
           } else {
             localStorage.removeItem(_authUrl)
+            localStorage.removeItem(_href + 'files')
+            window.GLOB.storeFiles = false
+
             this.setState({
               auth: false
             })

--
Gitblit v1.8.0