From 92108e6c93de657838bbd766a9eb4f27d85e1c2d Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期二, 05 五月 2020 16:41:28 +0800
Subject: [PATCH] 2020-05-05

---
 src/templates/sharecomponent/settingcomponent/index.jsx              |    9 
 src/templates/sharecomponent/tabscomponent/index.scss                |   99 ++
 src/templates/formtabconfig/index.jsx                                |  345 +--------
 src/templates/sharecomponent/chartcomponent/chartcompile/index.jsx   |    0 
 src/tabviews/scriptmanage/config.jsx                                 |    3 
 src/templates/comtableconfig/index.jsx                               |  627 ++++-------------
 src/templates/sharecomponent/searchcomponent/index.jsx               |    9 
 src/templates/sharecomponent/chartcomponent/index.jsx                |   56 +
 src/locales/zh-CN/model.js                                           |    1 
 src/templates/sharecomponent/fieldscomponent/index.jsx               |    8 
 src/templates/sharecomponent/columncomponent/index.jsx               |    9 
 src/templates/sharecomponent/tablecomponent/index.jsx                |    9 
 src/locales/en-US/model.js                                           |    1 
 src/templates/formtabconfig/source.jsx                               |   46 
 src/templates/sharecomponent/tabscomponent/tabform/index.scss        |    0 
 src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx   |    6 
 src/templates/sharecomponent/chartcomponent/index.scss               |    0 
 src/templates/sharecomponent/tabscomponent/index.jsx                 |  383 +++++++++++
 src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss |   12 
 src/templates/zshare/formconfig.jsx                                  |  103 ++
 src/templates/comtableconfig/source.jsx                              |   59 
 src/templates/sharecomponent/tabscomponent/tabform/index.jsx         |    4 
 src/templates/subtableconfig/index.jsx                               |   37 
 /dev/null                                                            |   41 -
 src/templates/sharecomponent/chartcomponent/chartcompile/index.scss  |    0 
 src/templates/comtableconfig/index.scss                              |  122 ---
 src/templates/sharecomponent/actioncomponent/index.jsx               |    9 
 src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx  |   26 
 src/templates/sharecomponent/chartgroupcomponent/index.jsx           |   10 
 29 files changed, 991 insertions(+), 1,043 deletions(-)

diff --git a/src/locales/en-US/model.js b/src/locales/en-US/model.js
index db9719b..3009892 100644
--- a/src/locales/en-US/model.js
+++ b/src/locales/en-US/model.js
@@ -246,6 +246,7 @@
   'model.tooltip.search.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��',
   'model.tooltip.action.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�',
   'model.tooltip.column.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�',
+  'model.tooltip.tabs.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃爣绛鹃〉銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬爣绛鹃〉鎷栬嚦姝ゅ娣诲姞銆�',
   'model.tooltip.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;',
   'model.tooltip.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�',
 }
\ No newline at end of file
diff --git a/src/locales/zh-CN/model.js b/src/locales/zh-CN/model.js
index 1360bd4..8c7f8b8 100644
--- a/src/locales/zh-CN/model.js
+++ b/src/locales/zh-CN/model.js
@@ -246,6 +246,7 @@
   'model.tooltip.search.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃悳绱€�嬩腑锛岄�夋嫨瀵瑰簲鎼滅储妗嗘嫋鑷虫澶勬坊鍔狅紱鎴栫偣鍑绘寜閽�婃坊鍔犳悳绱㈡潯浠躲�嬫壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ��',
   'model.tooltip.action.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃寜閽�嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬寜閽嫋鑷虫澶勬坊鍔狅紝濡傞�夋嫨鎸夐挳绫诲瀷涓鸿〃鍗曘�佹柊鏍囩椤电瓑鍚湁閰嶇疆椤甸潰鐨勬寜閽紝鍙湪宸︿晶宸ュ叿鏍�-鎸夐挳-鍙厤缃寜閽锛岀偣鍑绘寜閽畬鎴愮浉鍏抽厤缃�傛敞锛氬綋璁剧疆鎸夐挳鏄剧ず浣嶇疆涓鸿〃鏍兼椂锛屾樉绀哄垪浼氬鍔犳搷浣滃垪銆�',
   'model.tooltip.column.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃樉绀哄垪銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬樉绀哄垪鎷栬嚦姝ゅ娣诲姞锛涙垨鐐瑰嚮銆婃坊鍔犳樉绀哄垪銆嬫寜閽壒閲忔坊鍔狅紝閫夋嫨鎵归噺娣诲姞鏃讹紝闇�鎻愬墠閫夋嫨浣跨敤琛ㄣ�傛敞锛氭坊鍔犲悎骞跺垪鏃讹紝闇�璁剧疆鍙�夊垪銆�',
+  'model.tooltip.tabs.guide': '鍦ㄥ乏渚у伐鍏锋爮銆婃爣绛鹃〉銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬爣绛鹃〉鎷栬嚦姝ゅ娣诲姞銆�',
   'model.tooltip.func.innerface': '鍐呴儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠ableField绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愬強鎿嶄綔绫诲瀷;',
   'model.tooltip.func.outface': '澶栭儴鎺ュ彛: 鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屾彁浜ゆ暟鎹粡杩囧唴閮ㄥ嚱鏁板鐞嗗悗锛屼紶鍏ュ閮ㄦ帴鍙o紝鏈缃椂锛屾暟鎹細鐩存帴浼犲叆澶栭儴鎺ュ彛銆�',
 }
\ No newline at end of file
diff --git a/src/tabviews/scriptmanage/config.jsx b/src/tabviews/scriptmanage/config.jsx
index f6349f2..7a06701 100644
--- a/src/tabviews/scriptmanage/config.jsx
+++ b/src/tabviews/scriptmanage/config.jsx
@@ -11,8 +11,7 @@
     "columnfixed":false,
     "primaryKey":"ID",
     "order":"ID desc",
-    "onload":"true",
-    "subtabs":[]
+    "onload":"true"
   },
   tables: [{"TbName":"s_custom_script","Remark":"鑷畾涔夎剼鏈�"}],
   search: [
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
index 6a548b0..b3802e7 100644
--- a/src/templates/comtableconfig/index.jsx
+++ b/src/templates/comtableconfig/index.jsx
@@ -4,7 +4,7 @@
 import { is, fromJS } from 'immutable'
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
-import { Button, Card, Modal, Collapse, notification, Spin, Icon, Switch, Tooltip } from 'antd'
+import { Button, Card, Modal, Collapse, notification, Spin, Icon, Switch, Tooltip, Col } from 'antd'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -16,19 +16,16 @@
 import asyncComponent from '@/utils/asyncComponent'
 import TableComponent from '@/templates/sharecomponent/tablecomponent'
 import FieldsComponent from '@/templates/sharecomponent/fieldscomponent'
-// import ChartGroupComponent from '@/templates/sharecomponent/chartgroupcomponent'
+import ChartGroupComponent from '@/templates/sharecomponent/chartgroupcomponent'
 import SearchComponent from '@/templates/sharecomponent/searchcomponent'
 import ActionComponent from '@/templates/sharecomponent/actioncomponent'
 import ColumnComponent from '@/templates/sharecomponent/columncomponent'
+import TabsComponent from '@/templates/sharecomponent/tabscomponent'
+import ChartComponent from '@/templates/sharecomponent/chartcomponent'
 
-// import SettingForm from './settingform'
-import TabForm from '@/templates/zshare/tabform'
 import MenuForm from '@/templates/zshare/menuform'
-import TabDragElement from '@/templates/zshare/tabdragelement'
 import EditComponent from '@/templates/zshare/editcomponent'
 import SourceElement from '@/templates/zshare/dragsource'
-// import CreateFunc from '@/templates/zshare/createfunc'
-// import CreateInterface from '@/templates/zshare/createinterface'
 import Source from './source'
 import './index.scss'
 
@@ -52,7 +49,6 @@
     fields: null,            // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
     menuformlist: null,      // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
     formlist: null,          // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁
-    modaltype: '',           // 妯℃�佹绫诲瀷锛屾帶鍒舵ā鎬佹鏄剧ず
     card: null,              // 缂栬緫鍏冪礌
     menuloading: false,      // 鑿滃崟淇濆瓨涓�
     menucloseloading: false, // 鑿滃崟鍏抽棴鏃讹紝閫夋嫨淇濆瓨
@@ -67,7 +63,7 @@
     optionLibs: null,        // 鑷畾涔変笅鎷夐�夐」搴�
     thawButtons: [],         // 宸查�夋嫨瑕佽В鍐荤殑鎸夐挳
     activeKey: '0',          // 榛樿灞曞紑鍩烘湰淇℃伅
-    sqlVerifing: false,      // sql楠岃瘉
+    chartview: null,         // 褰撳墠瑙嗗浘
     pasteContent: null       // 绮樿创閰嶇疆淇℃伅
   }
 
@@ -109,10 +105,40 @@
 
     // 閰嶇疆榛樿鍊硷紝鍏煎
     _config.tabs = _config.tabs || []
-    _config.tabgroups = _config.tabgroups || ['tabs']
-    _config.setting.subtabs = _config.setting.subtabs || []
     _config.Template = 'CommonTable'
     _config.easyCode = _config.easyCode || ''
+
+    if (!_config.tabgroups) {
+      _config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
+    } else if (typeof(_config.tabgroups[0]) === 'string') {
+      let _tabgroups = []
+      _config.tabgroups.forEach(groupId => {
+        let _group = {
+          uuid: groupId,
+          sublist: fromJS(_config[groupId]).toJS()
+        }
+
+        delete _config[groupId]
+
+        _tabgroups.push(_group)
+      })
+
+      _config.tabgroups = _tabgroups
+    }
+
+    // 鍏煎鍥捐〃
+    if (!_config.charts) {
+      _config.expand = false
+      _config.charts = [{
+        uuid: Utils.getuuid(),
+        label: '',
+        title: '',
+        chartType: 'table',
+        icon: 'table',
+        Hide: 'false',
+        blacklist: []
+      }]
+    }
     
     let _oriActions = []
     if (_config.type === 'user') {
@@ -143,7 +169,7 @@
 
       // 閲嶇疆鏍囩ID
       _config.tabgroups.forEach(group => {
-        _config[group] = _config[group].map(tab => {
+        group.sublist = group.sublist.map(tab => {
           tab.uuid = Utils.getuuid()
           
           if (tab.linkTab) {
@@ -156,6 +182,7 @@
     }
 
     this.setState({
+      chartview: _config.charts[0].uuid,
       config: _config,
       activeKey: menu.activeKey || '0',
       optionLibs: optionLibs,
@@ -225,246 +252,6 @@
   }
 
   /**
-   * @description 鍏冪礌娣诲姞鎴栨嫋鍔ㄦ椂椤哄簭鍙樺寲
-   */
-  handleList = (type, list, card) => {
-    const { config } = this.state
-
-    if (list.length > config[card.groupId].length) {
-      list = list.filter(item => !item.origin)
-      this.handleTab(card)
-    }
-
-    this.setState({config: {...config, [card.groupId]: list}})
-  }
-  
-  /**
-   * @description 鏍囩缂栬緫锛岀瓫閫夊彲閫夌殑涓嬬骇鏍囩涓庡凡鍏宠仈鐨勪笅绾ф爣绛�
-   */
-  handleTab = (card) => {
-    const { config } = this.state
-
-    let menus = [
-      {value: '', text: '绌�'},
-      {value: 'mainTable', text: '涓昏〃'}
-    ]
-    let equalTabs = []
-    let supMenu = card.supMenu || ''
-    let equalTab = card.equalTab || []
-    let isuptab = true
-    let equalTabIds = []
-
-    config.tabgroups.forEach((groupId, i) => {
-      if (groupId === card.groupId) {
-        isuptab = false
-        config[card.groupId].forEach(tab => { // 鍙叧鑱旂殑鍚岀骇鏍囩
-          if (tab.uuid === card.uuid) return
-
-          equalTabIds.push(tab.uuid)
-          equalTabs.push(tab)
-        })
-      } else if (isuptab) {
-        config[groupId].forEach(tab => {
-          menus.push({
-            value: tab.uuid,
-            text: tab.label
-          })
-        })
-      }
-    })
-
-    if (supMenu && menus.filter(menu => menu.value === supMenu).length === 0) {
-      supMenu = ''
-    }
-
-    if (equalTab.length > 0) {
-      equalTab = equalTab.filter(tabId => equalTabIds.includes(tabId))
-    }
-
-
-    this.setState({
-      modaltype: 'tabs',
-      card: card,
-      formlist: [
-        {
-          type: 'text',
-          key: 'label',
-          label: this.state.dict['header.menu.tabName'],
-          initVal: card.label || '',
-          required: true
-        },
-        {
-          type: 'select',
-          key: 'type',
-          label: this.state.dict['header.form.tabType'],
-          initVal: card.type || 'SubTable',
-          required: true,
-          options: [{
-            value: 'SubTable',
-            text: this.state.dict['header.menu.tab.subtable']
-          }]
-        },
-        {
-          type: 'select',
-          key: 'linkTab',
-          label: this.state.dict['header.form.linkTab'],
-          initVal: card.linkTab || '',
-          required: false,
-          options: []
-        },
-        {
-          type: 'select',
-          key: 'icon',
-          label: this.state.dict['header.menu.icon'],
-          initVal: card.icon || '',
-          required: false,
-          options: [{
-            value: '',
-            text: this.state.dict['header.form.empty']
-          }, {
-            value: 'table',
-            text: 'table'
-          }, {
-            value: 'bar-chart',
-            text: 'bar-chart'
-          }, {
-            value: 'pie-chart',
-            text: 'pie-chart'
-          }, {
-            value: 'line-chart',
-            text: 'line-chart'
-          }]
-        },
-        {
-          type: 'select',
-          key: 'supMenu',
-          label: this.state.dict['header.form.supTab'],
-          initVal: supMenu,
-          required: false,
-          options: menus
-        },
-        {
-          type: 'mutilselect',
-          key: 'equalTab',
-          label: this.state.dict['header.form.equalTab'],
-          tooltip: '濡傛灉瀛愭爣绛句腑鍚湁鍒锋柊鍚岀骇鏍囩鐨勬寜閽紝鍦ㄦ澶勬坊鍔犻渶瑕佸埛鏂扮殑鏍囩銆�',
-          initVal: equalTab,
-          required: false,
-          options: equalTabs
-        },
-        {
-          type: 'text',
-          key: 'foreignKey',
-          label: '澶栭敭',
-          tooltip: '澶栭敭鏃ㄥ湪鏍囩椤典腑鎵ц榛樿鍑芥暟锛堟坊鍔狅級鏃讹紝鏇挎崲BID瀛楁',
-          initVal: card.foreignKey || '',
-          required: false
-        },
-        {
-          type: 'radio',
-          key: 'searchPass',
-          label: '涓昏〃鎼滅储',
-          initVal: card.searchPass || 'false',
-          tooltip: '浣跨敤涓昏〃鎼滅储鏉′欢鏃讹紝涓昏〃鐨勬悳绱㈡潯浠朵細浼犲叆瀛愯〃涓��',
-          required: false,
-          options: [{
-            value: 'true',
-            text: '浣跨敤'
-          }, {
-            value: 'false',
-            text: '涓嶄娇鐢�'
-          }]
-        }
-      ]
-    })
-  }
-
-  /**
-   * @description 鏍囩淇敼鍚庢彁浜や繚瀛�
-   */
-  handleSubmit = () => {
-    const { config } = this.state
-    this.tabsFormRef.handleConfirm().then(res => {
-      let _tabgroup = config[res.groupId].map(item => {
-        if (item.uuid === res.uuid) {
-          return res
-        } else {
-          return item
-        }
-      })
-      _tabgroup = _tabgroup.filter(item => !item.origin)
-
-      this.setState({
-        config: {...config, [res.groupId]: _tabgroup},
-        modaltype: ''
-      })
-    })
-  }
-
-  /**
-   * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎
-   */
-  editModalCancel = () => {
-    const { config, card } = this.state
-
-    if (card && card.focus) {
-      let _config = null
-
-      let _tabgroup = config[card.groupId].filter(item => item.uuid !== card.uuid)
-      _config = {...config, [card.groupId]: _tabgroup}
-
-      this.setState({
-        card: null,
-        config: _config,
-        modaltype: ''
-      })
-    } else {
-      this.setState({
-        card: null,
-        modaltype: ''
-      })
-    }
-  }
-
-  deleteElement = (element) => {
-    const { config, thawButtons } = this.state
-    let _this = this
-
-    confirm({
-      content: `纭畾鍒犻櫎<<${element.card.label}>>鍚楋紵`,
-      okText: this.state.dict['model.confirm'],
-      cancelText: this.state.dict['header.cancel'],
-      onOk() {
-        let _config = null
-
-        if (element.type === 'tabs') {
-          let _tabgroup = config[element.card.groupId].filter(item => {
-            if (item.uuid === element.card.uuid) {
-              return false
-            } else {
-              return true
-            }
-          })
-          _config = {...config, [element.card.groupId]: _tabgroup}
-        }
-
-        // 鍒犻櫎鎸夐挳鍏冪礌
-        let _delActions = _this.state.delActions
-        if (element.type === 'action' || element.type === 'tabs') {
-          _delActions.push(element)
-        }
-
-        _this.setState({
-          config: _config,
-          delActions: _delActions,
-          thawButtons: thawButtons.filter(key => key !== element.card.uuid)
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  /**
    * @description 涓夌骇鑿滃崟鍒囨崲妯℃澘
    */
   changeTemplate = () => {
@@ -506,48 +293,10 @@
 
     this.menuformRef.handleConfirm().then(res => {
       if (config.isAdd) {
-        if (config.search[0] && config.search[0].origin) {
-          config.search = config.search.filter(item => !item.origin)
-        }
-        if (config.action[0] && config.action[0].origin) {
-          config.action = config.action.filter(item => !item.origin)
-        }
-        if (config.columns[0] && config.columns[0].origin) {
-          config.columns = config.columns.filter(item => !item.origin)
-        }
-        if (config.tabs[0] && config.tabs[0].origin) {
-          config.tabs = config.tabs.filter(item => !item.origin)
-        }
-      }
-
-      let btnNames = config.action.map(item => item.label)
-      btnNames = Array.from(new Set(btnNames))
-      if (btnNames.length < config.action.length) {
-        notification.warning({
-          top: 92,
-          message: '鎸夐挳鍚嶇О涓嶅彲鐩稿悓锛�',
-          duration: 5
-        })
-        return
-      }
-
-      let tabNames = []
-      let tablength = 0
-      config.tabgroups.forEach(group => {
-        config[group].forEach(tab => {
-          tabNames.push(tab.label)
-        })
-        tablength += config[group].length
-      })
-      tabNames = Array.from(new Set(tabNames))
-
-      if (tabNames.length < tablength) {
-        notification.warning({
-          top: 92,
-          message: '鏍囩鍚嶇О涓嶅彲鐩稿悓锛�',
-          duration: 5
-        })
-        return
+        config.search = config.search.filter(item => !item.origin)
+        config.action = config.action.filter(item => !item.origin)
+        config.columns = config.columns.filter(item => !item.origin)
+        config.tabgroups[0].sublist = config.tabgroups[0].sublist.filter(item => !item.origin)
       }
 
       if (config.type === 'user') { // 浣跨敤宸叉湁鑿滃崟鏃讹紝榛樿娣诲姞鍏宠仈鏍囩id
@@ -559,11 +308,10 @@
         })
     
         config.tabgroups.forEach(group => {
-          config[group] = config[group].map(tab => {
+          group.sublist = group.sublist.map(tab => {
             if (!tab.linkTab) {
               tab.linkTab = Utils.getuuid()
             }
-  
             return tab
           })
         })
@@ -574,16 +322,9 @@
       let _pageParam = {...menu.PageParam, OpenType: res.opentype}
 
       // 鏈缃暟鎹簮鎴栨爣绛句笉鍚堟硶鏃讹紝鍚敤鐘舵�佷负false
-      if (_config.setting.interType === 'inner' && !_config.setting.innerFunc && !_config.setting.dataresource) {
+      let vresult = this.verifyconfig(_config)
+      if (vresult !== true) {
         _config.enabled = false
-      } else if (!_config.setting.primaryKey) {
-        _config.enabled = false
-      } else if (_config.tabgroups.length > 1) {
-        _config.tabgroups.forEach(group => {
-          if (_config[group].length === 0) {
-            _config.enabled = false
-          }
-        })
       }
 
       _config.funcs = [] // 椤甸潰鍙婂瓙椤甸潰瀛樺偍杩囩▼闆�
@@ -638,10 +379,8 @@
         }
       })
 
-      _config.tabgroups.forEach(groupId => {
-        if (_config[groupId].length === 0) return
-
-        _config[groupId].forEach(tab => {
+      _config.tabgroups.forEach(group => {
+        group.sublist.forEach(tab => {
           _config.funcs.push({
             type: 'tab',
             subtype: 'tab',
@@ -766,8 +505,8 @@
         btntabs.forEach(item => {
           _LText.push(`select '${item.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${item.sort * 10}' as Sort`)
         })
-        _config.tabgroups.forEach(groupId => {
-          _config[groupId].forEach(item => {
+        _config.tabgroups.forEach(group => {
+          group.sublist.forEach(item => {
             _sort++
             _LText.push(`select '${menu.MenuID}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${_sort * 10}' as Sort`)
           })
@@ -1071,13 +810,27 @@
 
                     return _btn
                   })
-                  _subconfig.tabgroups.forEach(_groupId => {
-                    _subconfig[_groupId] = _subconfig[_groupId].map(_tab => {
-                      _tab.uuid = Utils.getuuid()
-  
-                      if (_tab.linkTab) {
-                        _tab.linkTab = ''
+
+                  // 鍏煎宸叉湁缁撴瀯
+                  if (!_subconfig.tabgroups) {
+                    _subconfig.tabgroups = [{ uuid: 'tabs', sublist: [] }]
+                  } else if (typeof(_subconfig.tabgroups[0]) === 'string') {
+                    let _tabgroups = []
+                    _subconfig.tabgroups.forEach(groupId => {
+                      let _group = {
+                        uuid: groupId,
+                        sublist: fromJS(_subconfig[groupId]).toJS()
                       }
+                      delete _subconfig[groupId]
+                      _tabgroups.push(_group)
+                    })
+                    _subconfig.tabgroups = _tabgroups
+                  }
+
+                  _subconfig.tabgroups.forEach(group => {
+                    group.sublist = group.sublist.map(_tab => {
+                      _tab.uuid = Utils.getuuid()
+                      _tab.linkTab = Utils.getuuid()
 
                       return _tab
                     })
@@ -1316,107 +1069,44 @@
   onEnabledChange = () => {
     const { config } = this.state
 
+    let _enabled = !config.enabled
+    let result = this.verifyconfig(config)
+    if (_enabled && result !== true) {
+      notification.warning({
+        top: 92,
+        message: result,
+        duration: 5
+      })
+      return
+    }
+
+    this.setState({
+      config: {...config, enabled: _enabled}
+    })
+  }
+
+  /**
+   * @description 鏍¢獙閰嶇疆淇℃伅鐨勫悎娉曟��
+   */
+  verifyconfig = (config) => {
     let tabinvalid = true
     if (config.tabgroups.length > 1) {
       config.tabgroups.forEach(group => {
-        if (config[group].length === 0) {
+        if (group.sublist.length === 0) {
           tabinvalid = false
         }
       })
     }
 
     if (config.setting.interType === 'inner' && !config.setting.innerFunc && !config.setting.dataresource) {
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟灏氭湭璁剧疆鏁版嵁婧愶紝涓嶅彲鍚敤锛�',
-        duration: 5
-      })
+      return '鑿滃崟灏氭湭璁剧疆鏁版嵁婧愶紝涓嶅彲鍚敤锛�'
     } else if (!config.setting.primaryKey) {
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟灏氭湭璁剧疆涓婚敭锛屼笉鍙惎鐢紒',
-        duration: 5
-      })
+      return '鑿滃崟灏氭湭璁剧疆涓婚敭锛屼笉鍙惎鐢紒'
     } else if (!tabinvalid) {
-      notification.warning({
-        top: 92,
-        message: '鑿滃崟鏍囩椤佃缃敊璇紙澶氳鏍囩鍐咃紝琛屾爣绛句笉鍙负绌猴級锛屼笉鍙惎鐢紒',
-        duration: 5
-      })
+      return '鑿滃崟鏍囩椤佃缃敊璇紙瀛樺湪澶氳鏍囩鏃讹紝琛屾爣绛句笉鍙负绌猴級锛�'
     } else {
-      this.setState({
-        config: {...config, enabled: !config.enabled}
-      })
+      return true
     }
-  }
-
-  /**
-   * @description 澧炲姞鏍囩椤靛垎缁�
-   */
-  addTabGroup = () => {
-    let _this = this
-    let _config = fromJS(this.state.config).toJS()
-
-    confirm({
-      content: `纭畾鏂板缓鏍囩缁勫悧锛焋,
-      okText: this.state.dict['model.confirm'],
-      cancelText: this.state.dict['header.cancel'],
-      onOk() {
-        let newgroup = 'tabs' + Utils.getuuid()
-
-        _config.tabgroups.push(newgroup)
-        _config[newgroup] = []
-
-        _this.setState({
-          config: _config
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  /**
-   * @description 鍒犻櫎鏍囩椤靛垎缁�
-   */
-  delTabGroup = (groupId) => {
-    let _this = this
-    let _config = fromJS(this.state.config).toJS()
-
-    confirm({
-      content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋,
-      okText: this.state.dict['model.confirm'],
-      cancelText: this.state.dict['header.cancel'],
-      onOk() {
-
-        _config.tabgroups = _config.tabgroups.filter(group => group !== groupId)
-        delete _config[groupId]
-
-        _this.setState({
-          config: _config
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  handleGroup = (index, type) => {
-    let config = fromJS(this.state.config).toJS()
-    
-    if (type === 'up') {
-      config.tabgroups.splice(index, 0, config.tabgroups.splice(index - 1, 1)[0])
-    } else {
-      config.tabgroups.splice(index, 0, config.tabgroups.splice(index + 1, 1)[0])
-    }
-
-    this.setState({
-      config: config
-    })
-
-    notification.success({
-      top: 92,
-      message: '璋冩暣鎴愬姛',
-      duration: 2
-    })
   }
 
   /**
@@ -1501,6 +1191,18 @@
   }
 
   /**
+   * @description 鏇存柊鏍囩閰嶇疆淇℃伅
+   */
+  updatetabs = (config, delcards) => {
+    const { delActions } = this.state
+
+    this.setState({
+      config: config,
+      delActions: delcards ? [...delActions, ...delcards] : delActions
+    })
+  }
+
+  /**
    * @description 鏇存柊閰嶇疆淇℃伅
    */
   updateconfig = (config) => {
@@ -1510,13 +1212,13 @@
   }
 
   render () {
-    const { modaltype, activeKey, config } = this.state
+    const { activeKey, config, chartview } = this.state
 
     const confActions = config.action.filter(_action => !_action.origin && ['pop', 'popview', 'blank', 'tab'].includes(_action.OpenType))
 
     let configTabs = []
     config.tabgroups.forEach(group => {
-      configTabs.push(...config[group])
+      configTabs.push(...group.sublist)
     })
 
     return (
@@ -1660,73 +1362,64 @@
                 optionLibs={this.state.optionLibs}
                 updatesearch={this.updatesearch}
               />
-              <ActionComponent
+              <div className="chart-view" style={{position: 'relative'}}>
+                {/* 瑙嗗浘缁� */}
+                <ChartGroupComponent
+                  config={config}
+                  sysRoles={this.props.sysRoles}
+                  updatechartgroup={this.updatechartgroup}
+                />
+                {config.charts.map(item => {
+                  if (!config.expand && chartview !== item.uuid) return ''
+
+                  if (item.chartType === 'table') {
+                    return (
+                      <Col span={item.width || 24} key={item.uuid}>
+                        {config.charts.length > 1 ? <p className="chart-title">{item.title}</p> : null}
+                        <ActionComponent
+                          type="main"
+                          menu={{ MenuID: this.props.menu.MenuID, MenuName: this.props.menu.MenuName, MenuNo: this.props.menu.MenuNo }}
+                          config={config}
+                          tabs={this.state.tabviews}
+                          menuformRef={this.menuformRef}
+                          pasteContent={this.state.pasteContent}
+                          usefulFields={this.props.permFuncField}
+                          setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
+                          updateaction={this.updateaction}
+                        />
+                        <ColumnComponent
+                          config={config}
+                          menu={this.props.menu}
+                          sysRoles={this.props.sysRoles}
+                          pasteContent={this.state.pasteContent}
+                          updatecolumn={this.updateconfig}
+                        />
+                      </Col>
+                    )
+                  } else {
+                    return (
+                      <Col span={item.width} key={item.uuid}>
+                        <ChartComponent
+                          plot={item}
+                          config={config}
+                          plotchange={this.updateconfig}
+                        />
+                      </Col>
+                    )
+                  }
+                })}
+              </div>
+              {/* 鏍囩缁� */}
+              <TabsComponent
                 type="main"
-                menu={{ MenuID: this.props.menu.MenuID, MenuName: this.props.menu.MenuName, MenuNo: this.props.menu.MenuNo }}
                 config={config}
                 tabs={this.state.tabviews}
-                menuformRef={this.menuformRef}
-                pasteContent={this.state.pasteContent}
-                usefulFields={this.props.permFuncField}
-                setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
-                updateaction={this.updateaction}
+                setSubConfig={(item) => this.setSubConfig(item, 'tab')}
+                updatetabs={this.updatetabs}
               />
-              {/* 鏄剧ず鍒� */}
-              <ColumnComponent
-                config={config}
-                menu={this.props.menu}
-                sysRoles={this.props.sysRoles}
-                pasteContent={this.state.pasteContent}
-                updatecolumn={this.updateconfig}
-              />
-              {/* 鏍囩缁� */}
-              {config.tabgroups.map((groupId, index) => {
-                return (
-                  <div key={index} className="tab-list">
-                    {index === 0 ? <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃爣绛鹃〉銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬爣绛鹃〉鎷栬嚦姝ゅ娣诲姞銆�">
-                      <Icon type="question-circle" />
-                    </Tooltip> : null}
-                    {index !== (config.tabgroups.length - 1) ?
-                      <Icon type="arrow-down" onClick={() => {this.handleGroup(index, 'down')}} /> : null
-                    }
-                    {index !== 0 ? <Icon type="arrow-up" onClick={() => {this.handleGroup(index, 'up')}} /> : null}
-                    {index === 0 ? <Icon type="plus" onClick={this.addTabGroup} /> : null}
-                    {index !== 0 ? <Icon type="delete" onClick={() => {this.delTabGroup(groupId)}} /> : null}
-                    <TabDragElement
-                      type="tabs"
-                      groupId={groupId}
-                      list={config[groupId]}
-                      handleList={this.handleList}
-                      handleMenu={this.handleTab}
-                      deleteMenu={this.deleteElement}
-                      doubleClickCard={(tab) => this.setSubConfig(tab, 'tab')}
-                      placeholder={this.state.dict['header.form.tab.placeholder']}
-                    />
-                  </div>)
-              })}
             </Card>
           </div>
         </DndProvider>
-        {/* 鏍囩缂栬緫 */}
-        <Modal
-          title={this.state.dict['header.modal.tabs.edit']}
-          visible={modaltype === 'tabs'}
-          width={750}
-          maskClosable={false}
-          onOk={this.handleSubmit}
-          onCancel={this.editModalCancel}
-          destroyOnClose
-        >
-          <TabForm
-            type="tabs"
-            dict={this.state.dict}
-            card={this.state.card}
-            tabs={this.state.tabviews}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleSubmit}
-            wrappedComponentRef={(inst) => this.tabsFormRef = inst}
-          />
-        </Modal>
         {/* 杩斿洖鏃舵湭淇濆瓨鎻愮ず */}
         <Modal
           bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
diff --git a/src/templates/comtableconfig/index.scss b/src/templates/comtableconfig/index.scss
index 05d8a28..ca494f3 100644
--- a/src/templates/comtableconfig/index.scss
+++ b/src/templates/comtableconfig/index.scss
@@ -170,117 +170,25 @@
       position: relative;
       padding: 0 0 40px;
 
-      .tab-list {
-        position: relative;
-        padding: 30px 20px 0px;
-        .ant-switch {
-          position: absolute;
-          right: 20px;
-          top: 20px;
-        }
-        > .ant-row {
-          min-height: 47px;
-          .page-card {
-            position: relative;
-            padding: 0px;
-            > div {
-              padding: 12px 0px 0px;
-              cursor: move;
-            }
-          }
-          .ant-tabs-tab {
-            cursor: default;
-            .edit {
-              position: absolute;
-              left: 0;
-              top: 0px;
-              color: #1890ff;
-              cursor: pointer;
-              display: none;
-            }
-            .edit.close {
-              left: 20px;
-              color: #ff4d4f;
-            }
-          }
-          .ant-tabs-bar {
-            min-height: 55px;
-          }
-          .ant-tabs-tab:hover {
-            .edit {
-              display: inline-block;
-            }
-          }
-          .ant-tabs-content {
-            .ant-tabs-tabpane img {
-              width: 100%;
-            }
-          }
-        }
-        > .anticon-question-circle {
-          color: #c49f47;
-          position: absolute;
-          left: 5px;
-          top: 20px;
-        }
-        > .anticon-plus {
-          position: absolute;
+      .chart-view {
+        margin-bottom: 70px;
+
+        .chart-title {
+          margin-bottom: 15px;
+          color: rgba(0, 0, 0, 0.85);
+          font-weight: 400;
           font-size: 18px;
-          right: 25px;
-          top: 50px;
-          z-index: 1;
-          color: #26C281;
-          cursor: pointer;
-        }
-        > .anticon-delete {
-          position: absolute;
-          font-size: 19px;
-          right: 25px;
-          top: 50px;
-          z-index: 1;
-          color: #ff4d4f;
-          cursor: pointer;
-        }
-        > .anticon-arrow-up {
-          position: absolute;
-          right: 55px;
-          font-size: 19px;
-          z-index: 1;
-          top: 50px;
-          color: #1890ff;
-          cursor: pointer;
-        }
-        > .anticon-arrow-down {
-          position: absolute;
-          right: 55px;
-          font-size: 19px;
-          z-index: 1;
-          top: 50px;
-          color: purple;
-          cursor: pointer;
-        }
-        > .anticon-arrow-down + .anticon-arrow-up {
-          right: 85px;
-        }
-        .ant-tabs-nav-container-scrolling {
-          margin-right: 50px;
+          line-height: 25px;
+          height: 35px;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          overflow: hidden;
+          max-width: 50%;
+          padding-top: 10px;
+          padding-left: 30px;
         }
       }
-      // > .anticon-setting {
-      //   position: absolute;
-      //   font-size: 18px;
-      //   right: 7px;
-      //   top: 10px;
-      //   padding: 10px;
-      //   z-index: 1;
-      // }
     }
-    // .anticon-question-circle {
-    //   color: #c49f47;
-    //   position: relative;
-    //   left: -15px;
-    //   top: 5px;
-    // }
   }
   .setting {
     overflow-y: scroll;
diff --git a/src/templates/comtableconfig/settingform/index.jsx b/src/templates/comtableconfig/settingform/index.jsx
deleted file mode 100644
index ef66b1f..0000000
--- a/src/templates/comtableconfig/settingform/index.jsx
+++ /dev/null
@@ -1,375 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon, notification } from 'antd'
-import { formRule } from '@/utils/option.js'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const { TextArea } = Input
-
-class SettingForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object, // 瀛楀吀椤�
-    menu: PropTypes.object,
-    data: PropTypes.object,
-    columns: PropTypes.array,
-    usefulFields: PropTypes.array,
-    inputSubmit: PropTypes.any     // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    interType: this.props.data.interType || 'inner',
-    columns: this.props.columns.filter(item => item.field && item.type !== 'colspan'),
-    interReadonly: false,
-    primaryKey: ''
-  }
-
-  UNSAFE_componentWillMount() {
-    const { data, columns } = this.props
-
-    let primaryKey = data.primaryKey
-    if (primaryKey) {
-      let field = columns.filter(column => column.field === primaryKey)
-      if (field.length !== 1) {
-        primaryKey = ''
-      }
-    }
-    if (!primaryKey) {
-      columns.forEach(col => {
-        if (col.field.toLowerCase() === 'id') {
-          primaryKey = col.field
-        }
-      })
-    }
-
-    this.setState({
-      interReadonly: data.sysInterface === 'true',
-      primaryKey: primaryKey
-    })
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          values.actionfixed = values.actionfixed === 'true'
-          values.columnfixed = values.columnfixed === 'true'
-
-          if (values.interType === 'inner' && !values.innerFunc && !values.dataresource) {
-            notification.warning({
-              top: 92,
-              message: '璇疯嚜瀹氫箟鍑芥暟鎴栧~鍐欐暟鎹簮锛�',
-              duration: 5
-            })
-          } else {
-
-            let error = Utils.verifySql(values.dataresource)
-
-            if (error) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
-                duration: 5
-              })
-              return
-            }
-
-            resolve(values)
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  onChange = (e) => {
-    this.setState({
-      interType: e.target.value
-    }, () => {
-      if (e.target.value === 'inner') return
-
-      let _type = this.props.form.getFieldValue('sysInterface')
-      if (_type === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
-        this.setState({
-          interReadonly: true
-        })
-      } else {
-        this.setState({
-          interReadonly: false
-        })
-      }
-    })
-  }
-
-  onSysChange = (e) => {
-    if (e.target.value === 'true') {
-      this.props.form.setFieldsValue({
-        interface: window.GLOB.mainSystemApi || ''
-      })
-      this.setState({
-        interReadonly: true
-      })
-    } else {
-      this.setState({
-        interReadonly: false
-      })
-    }
-  }
-
-  selectChange = (val) => {
-    this.props.form.setFieldsValue({
-      order: `${val} desc`
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  render() {
-    const { data, dict, menu, usefulFields } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { interType, columns, primaryKey } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    let str = '^(' + usefulFields.join('|') + ')'
-    let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-    return (
-      <Form {...formItemLayout} className="ant-advanced-search-form commontable-setting-form" id="commontable-setting-form">
-        <Row gutter={24}>
-          <Col span={12}>
-            <Form.Item label="琛ㄥ悕">
-              {getFieldDecorator('tableName', {
-                initialValue: data.tableName || '',
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '琛ㄥ悕!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="琛ㄦ牸灞炴��">
-              {getFieldDecorator('tableType', {
-                initialValue: data.tableType || 'checkbox'
-              })(
-                <Select
-                  getPopupContainer={() => document.getElementById('commontable-setting-form')}
-                >
-                  <Select.Option value="">涓嶅彲閫�</Select.Option>
-                  <Select.Option value="radio">鍗曢��</Select.Option>
-                  <Select.Option value="checkbox">澶氶��</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label={dict['header.form.intertype']}>
-              {getFieldDecorator('interType', {
-                initialValue: data.interType || 'inner'
-              })(
-                <Radio.Group onChange={this.onChange}>
-                  <Radio value="inner">{dict['header.form.interface.inner']}</Radio>
-                  <Radio value="outer">{dict['header.form.interface.outer']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.sysInterface']}>
-              {getFieldDecorator('sysInterface', {
-                initialValue: data.sysInterface || 'false'
-              })(
-                <Radio.Group onChange={this.onSysChange}>
-                  <Radio value="true">{dict['header.form.true']}</Radio>
-                  <Radio value="false">{dict['header.form.false']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.interface']}>
-              {getFieldDecorator('interface', {
-                initialValue: data.sysInterface === 'true' ? (window.GLOB.mainSystemApi || '') : (data.interface || ''),
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + dict['header.form.interface'] + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={this.state.interReadonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.outerFunc']}>
-              {getFieldDecorator('outerFunc', {
-                initialValue: data.outerFunc || '',
-                rules: [
-                  {
-                    pattern: formRule.func.pattern,
-                    message: formRule.func.message
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" overlayClassName="middle" title={`鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠�${usefulFields.join(', ')}绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愩�俙}>
-                <Icon type="question-circle" />
-                {dict['header.form.innerFunc']}
-              </Tooltip>
-            }>
-              {getFieldDecorator('innerFunc', {
-                initialValue: data.innerFunc || '',
-                rules: [
-                  {
-                    pattern: _patten,
-                    message: formRule.func.innerMessage
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={24} style={{paddingLeft: '7px'}}>
-            <Form.Item labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} } help={'鏁版嵁ID锛�' + menu.MenuID} label={
-              <Tooltip placement="topLeft" title="浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愶紝鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�">
-                <Icon type="question-circle" />
-                {'鏁版嵁婧�'}
-              </Tooltip>
-            }>
-              {getFieldDecorator('dataresource', {
-                initialValue: data.dataresource || ''
-              })(<TextArea rows={4} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鏌ヨ鏃讹紝鎼滅储鏉′欢浠here鏉′欢鎷兼帴杩涘叆sql锛岀粺璁℃椂锛屽皢鏁版嵁婧愪腑浠モ�淍+鎼滅储瀛楁鈥濈殑鍐呭锛屼互鎼滅储鏉′欢涓殑鍊艰繘琛屾浛鎹㈠悗锛屾彁浜ゆ煡璇紝娉細鏌ヨ绫诲瀷浠呭湪浣跨敤绯荤粺鍑芥暟鏃舵湁鏁堛��">
-                <Icon type="question-circle" />
-                {dict['header.form.queryType']}
-              </Tooltip>
-            }>
-              {getFieldDecorator('queryType', {
-                initialValue: data.queryType || 'query'
-              })(
-                <Radio.Group>
-                  <Radio value="query">{dict['header.form.query']}</Radio>
-                  <Radio value="statistics">{dict['header.form.statistics']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          <Col span={12}>
-            <Form.Item label="鍥哄畾鎸夐挳">
-              {getFieldDecorator('actionfixed', {
-                initialValue: data.actionfixed ? 'true' : 'false'
-              })(
-                <Radio.Group>
-                  <Radio value="true">{dict['header.form.true']}</Radio>
-                  <Radio value="false">{dict['header.form.false']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鍥哄畾琛ㄥご">
-              {getFieldDecorator('columnfixed', {
-                initialValue: data.columnfixed ? 'true' : 'false'
-              })(
-                <Radio.Group>
-                  <Radio value="true">{dict['header.form.true']}</Radio>
-                  <Radio value="false">{dict['header.form.false']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="涓婚敭">
-              {getFieldDecorator('primaryKey', {
-                initialValue: primaryKey || ''
-              })(
-                <Select
-                  getPopupContainer={() => document.getElementById('commontable-setting-form')}
-                  onChange={this.selectChange}
-                >
-                  <Select.Option key='unset' value="">鏈缃�</Select.Option>
-                  {columns.map((option, index) =>
-                    <Select.Option id={option.uuid} title={option.label} key={index} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="榛樿鎺掑簭">
-              {getFieldDecorator('order', {
-                initialValue: data.order || (primaryKey ? primaryKey + ' desc' : ''),
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '榛樿鎺掑簭瀛楁!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="ID asc, UID desc" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鍒濆鍖�">
-              {getFieldDecorator('onload', {
-                initialValue: data.onload || 'true'
-              })(
-                <Select>
-                  <Select.Option value="true">鍔犺浇鏁版嵁</Select.Option>
-                  <Select.Option value="false">涓嶅姞杞芥暟鎹�</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/templates/comtableconfig/settingform/index.scss b/src/templates/comtableconfig/settingform/index.scss
deleted file mode 100644
index cd1a9f6..0000000
--- a/src/templates/comtableconfig/settingform/index.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-.ant-advanced-search-form.commontable-setting-form {
-  .textarea {
-    .ant-form-item-label {
-      width: 16.3%;
-    }
-    .ant-form-item-control-wrapper {
-      width: 83.33333333%;
-    }
-  }
-  .anticon-question-circle {
-    color: #c49f47;
-    margin-right: 3px;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
index 06db883..502fe78 100644
--- a/src/templates/comtableconfig/source.jsx
+++ b/src/templates/comtableconfig/source.jsx
@@ -22,8 +22,7 @@
       innerFunc: '',
       interface: '',
       outerFunc: '',
-      onload: 'true',
-      subtabs: []
+      onload: 'true'
     },
     tables: [],
     search: [
@@ -170,31 +169,37 @@
       show: 'horizontal',
       Width: 120
     },
-    tabs: [
-      {
-        origin: true,          // 鏄惁涓虹ず渚�
-        groupId: 'tabs',
-        uuid: Utils.getuuid(),
-        label: 'tab1',
-        icon: '',
-        type: 'SubTable',
-        linkTab: '',
-        subtabs: [],
-        supMenu: ''
-      },
-      {
-        origin: true,
-        groupId: 'tabs',
-        uuid: Utils.getuuid(),
-        label: 'tab2',
-        icon: '',
-        type: 'SubTable',
-        linkTab: '',
-        subtabs: [],
-        supMenu: ''
-      }
-    ],
-    tabgroups: ['tabs']
+    tabgroups: [{
+      uuid: 'tabs',
+      sublist: [
+        {
+          origin: true,          // 鏄惁涓虹ず渚�
+          uuid: Utils.getuuid(),
+          label: 'tab1',
+          type: 'SubTable',
+          linkTab: '',
+          supMenu: ''
+        },
+        {
+          origin: true,
+          uuid: Utils.getuuid(),
+          label: 'tab2',
+          type: 'SubTable',
+          linkTab: '',
+          supMenu: ''
+        }
+      ]
+    }],
+    expand: false,
+    charts: [{
+      uuid: Utils.getuuid(),
+      label: '',
+      title: '',
+      chartType: 'table',
+      icon: 'table',
+      Hide: 'false',
+      blacklist: []
+    }]
   }
 
   searchItems = [
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index cd8d82f..5571f51 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -14,17 +14,17 @@
 import { getModalForm, getActionForm } from '@/templates/zshare/formconfig'
 import { queryTableSql } from '@/utils/option.js'
 
+import TabsComponent from '@/templates/sharecomponent/tabscomponent'
+
 import ModalForm from '@/templates/zshare/modalform'
 import PasteForm from '@/templates/zshare/pasteform'
 import ActionForm from './actionform'
 import SettingForm from './settingform'
 import DragElement from './dragelement'
 import GroupForm from './groupform'
-import TabForm from '@/templates/zshare/tabform'
 import EditCard from '@/templates/zshare/editcard'
 import VerifyCard from '@/templates/zshare/verifycard'
 import MenuForm from '@/templates/zshare/menuform'
-import TabDragElement from '@/templates/zshare/tabdragelement'
 import SourceElement from '@/templates/zshare/dragsource'
 import CreateFunc from '@/templates/zshare/createfunc'
 import Source from './source'
@@ -121,6 +121,24 @@
           }
         })
       })
+    }
+
+    if (!_config.tabgroups) {
+      _config.tabgroups = [{ uuid: 'tabs', sublist: [] }]
+    } else if (typeof(_config.tabgroups[0]) === 'string') {
+      let _tabgroups = []
+      _config.tabgroups.forEach(groupId => {
+        let _group = {
+          uuid: groupId,
+          sublist: fromJS(_config[groupId]).toJS()
+        }
+
+        delete _config[groupId]
+
+        _tabgroups.push(_group)
+      })
+
+      _config.tabgroups = _tabgroups
     }
 
     if (menu && menu.LongParam && menu.LongParam.columns) {
@@ -348,15 +366,7 @@
   handleList = (type, list, card, groupId, elementId) => {
     const { config } = this.state
 
-    if (type === 'tabs') { // 鏍囩椤佃皟鏁撮『搴忔垨娣诲姞鍏冪礌
-      if (list.length > config[card.groupId].length) {
-        list = list.filter(item => !item.origin)
-
-        this.handleTab(card)
-      }
-
-      this.setState({config: {...config, [card.groupId]: list}})
-    } else if (type === 'action') {
+    if (type === 'action') {
       if (list.length > config.action.length) {
   
         this.handleAction(card)
@@ -509,127 +519,6 @@
     })
   }
 
-  handleTab = (card) => {
-    const { config } = this.state
-
-    let menus = [
-      {value: '', text: '绌�'},
-      {value: 'mainTable', text: '涓绘暟鎹�'}
-    ]
-    let equalTabs = []
-    let supMenu = card.supMenu || ''
-    let equalTab = card.equalTab || []
-    let isuptab = true
-    let equalTabIds = []
-
-    config.tabgroups.forEach((groupId, i) => {
-      if (groupId === card.groupId) {
-        isuptab = false
-        config[card.groupId].forEach(tab => { // 鍙叧鑱旂殑鍚岀骇鏍囩
-          if (tab.uuid === card.uuid) return
-
-          equalTabIds.push(tab.uuid)
-          equalTabs.push(tab)
-        })
-      } else if (isuptab) {
-        config[groupId].forEach(tab => {
-          menus.push({
-            value: tab.uuid,
-            text: tab.label
-          })
-        })
-      }
-    })
-
-    if (supMenu && menus.filter(menu => menu.value === supMenu).length === 0) {
-      supMenu = ''
-    }
-
-    if (equalTab.length > 0) {
-      equalTab = equalTab.filter(tabId => equalTabIds.includes(tabId))
-    }
-
-    this.setState({
-      modaltype: 'tabs',
-      card: card,
-      formlist: [
-        {
-          type: 'text',
-          key: 'label',
-          label: this.state.dict['header.menu.tabName'],
-          initVal: card.label || '',
-          required: true
-        },
-        {
-          type: 'select',
-          key: 'type',
-          label: this.state.dict['header.form.tabType'],
-          initVal: card.type || 'SubTable',
-          required: true,
-          options: [{
-            value: 'SubTable',
-            text: this.state.dict['header.menu.tab.subtable']
-          }]
-        },
-        {
-          type: 'select',
-          key: 'linkTab',
-          label: '鍏宠仈鏍囩',
-          initVal: card.linkTab || '',
-          required: false,
-          options: []
-        },
-        {
-          type: 'select',
-          key: 'icon',
-          label: this.state.dict['header.menu.icon'],
-          initVal: card.icon || '',
-          required: false,
-          options: [{
-            value: '',
-            text: this.state.dict['header.form.empty']
-          }, {
-            value: 'table',
-            text: 'table'
-          }, {
-            value: 'bar-chart',
-            text: 'bar-chart'
-          }, {
-            value: 'pie-chart',
-            text: 'pie-chart'
-          }, {
-            value: 'line-chart',
-            text: 'line-chart'
-          }]
-        },
-        {
-          type: 'select',
-          key: 'supMenu',
-          label: this.state.dict['header.form.supTab'],
-          initVal: supMenu,
-          required: false,
-          options: menus
-        },
-        {
-          type: 'mutilselect',
-          key: 'equalTab',
-          label: this.state.dict['header.form.equalTab'],
-          tooltip: '濡傛灉瀛愭爣绛句腑鍚湁鍒锋柊鍚岀骇鏍囩鐨勬寜閽紝鍦ㄦ澶勬坊鍔犻渶瑕佸埛鏂扮殑鏍囩銆�',
-          initVal: equalTab,
-          required: false,
-          options: equalTabs
-        },
-        {
-          type: 'text',
-          key: 'foreignKey',
-          label: '澶栭敭',
-          tooltip: '澶栭敭鏃ㄥ湪鏍囩椤典腑鎵ц榛樿鍑芥暟锛堟坊鍔狅級鏃讹紝鏇挎崲BID瀛楁',
-          initVal: card.foreignKey || '',
-          required: false
-        }
-      ]
-    })
-  }
 
   /**
    * @description 鎼滅储銆佹寜閽�佹樉绀哄垪淇敼鍚庢彁浜や繚瀛�
@@ -789,22 +678,6 @@
           modaltype: ''
         })
       })
-    } else if (modaltype === 'tabs') {
-      this.tabsFormRef.handleConfirm().then(res => {
-        let _tabgroup = config[res.groupId].map(item => {
-          if (item.uuid === res.uuid) {
-            return res
-          } else {
-            return item
-          }
-        })
-        _tabgroup = _tabgroup.filter(item => !item.origin)
-
-        this.setState({
-          config: {...config, [res.groupId]: _tabgroup},
-          modaltype: ''
-        })
-      })
     }
   }
 
@@ -822,9 +695,6 @@
       } else if (modaltype === 'actionEdit') {
         let _action = config.action.filter(item => item.uuid !== card.uuid)
         _config = {...config, action: _action}
-      } else if (modaltype === 'tabs') {
-        let _tabgroup = config[card.groupId].filter(item => item.uuid !== card.uuid)
-        _config = {...config, [card.groupId]: _tabgroup}
       } else {
         _config = config
       }
@@ -959,16 +829,7 @@
         let _config = JSON.parse(JSON.stringify(_this.state.config))
         let _delActions = _this.state.delActions
 
-        if (element.type === 'tabs') {
-          _config[element.card.groupId] = _config[element.card.groupId].filter(item => {
-            if (item.uuid === element.card.uuid) {
-              return false
-            } else {
-              return true
-            }
-          })
-          _delActions.push(element.card.uuid)
-        } else if (element.type === 'search') {
+        if (element.type === 'search') {
           _config.groups = _config.groups.map(group => {
             group.sublist = group.sublist.filter(item => item.uuid !== element.card.uuid)
             return group
@@ -1057,25 +918,6 @@
         return
       }
 
-      let tabNames = []
-      let tablength = 0
-      config.tabgroups.forEach(group => {
-        config[group].forEach(tab => {
-          tabNames.push(tab.label)
-        })
-        tablength += config[group].length
-      })
-      tabNames = Array.from(new Set(tabNames))
-
-      if (tabNames.length < tablength) {
-        notification.warning({
-          top: 92,
-          message: '鏍囩鍚嶇О涓嶅彲鐩稿悓锛�',
-          duration: 5
-        })
-        return
-      }
-
       let _LongParam = ''
       let _config = {...config, tables: this.state.selectedTables}
 
@@ -1088,8 +930,8 @@
 
       // 鏍囩涓嶅悎娉曟椂锛屽惎鐢ㄧ姸鎬佷负false
       if (_config.tabgroups.length > 1) {
-        _config.tabgroups.forEach(groupId => {
-          if (_config[groupId].length === 0) {
+        _config.tabgroups.forEach(group => {
+          if (group.sublist.length === 0) {
             _config.enabled = false
           }
         })
@@ -1142,10 +984,8 @@
         }
       })
 
-      _config.tabgroups.forEach(groupId => {
-        if (_config[groupId].length === 0) return
-
-        _config[groupId].forEach(tab => {
+      _config.tabgroups.forEach(group => {
+        group.sublist.forEach(tab => {
           _config.funcs.push({
             type: 'tab',
             subtype: 'tab',
@@ -1256,8 +1096,8 @@
         
         let _LText = []
 
-        config.tabgroups.forEach(groupId => {
-          config[groupId].forEach(item => {
+        config.tabgroups.forEach(group => {
+          group.sublist.forEach(item => {
             _sort++
             _LText.push(`select '${btnTab.uuid}' as MenuID ,'${item.linkTab}' as Tabid,'${item.label}' as TabName ,'${_sort * 10}' as Sort`)
           })
@@ -1792,7 +1632,7 @@
     let tabinvalid = true
     if (config.tabgroups.length > 1) {
       config.tabgroups.forEach(group => {
-        if (config[group].length === 0) {
+        if (group.sublist.length === 0) {
           tabinvalid = false
         }
       })
@@ -1854,48 +1694,7 @@
     }
   }
 
-  addTabGroup = () => {
-    let _this = this
-    let _config = JSON.parse(JSON.stringify(this.state.config))
 
-    confirm({
-      content: `纭畾鏂板缓鏍囩缁勫悧锛焋,
-      okText: this.state.dict['model.confirm'],
-      cancelText: this.state.dict['header.cancel'],
-      onOk() {
-        let newgroup = 'tabs' + Utils.getuuid()
-
-        _config.tabgroups.push(newgroup)
-        _config[newgroup] = []
-
-        _this.setState({
-          config: _config,
-        })
-      },
-      onCancel() {}
-    })
-  }
-
-  delTabGroup = (groupId) => {
-    let _this = this
-    let _config = JSON.parse(JSON.stringify(this.state.config))
-
-    confirm({
-      content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋,
-      okText: this.state.dict['model.confirm'],
-      cancelText: this.state.dict['header.cancel'],
-      onOk() {
-
-        _config.tabgroups = _config.tabgroups.filter(group => group !== groupId)
-        delete _config[groupId]
-
-        _this.setState({
-          config: _config
-        })
-      },
-      onCancel() {}
-    })
-  }
 
   handleGroup = (group) => {
     let editgroup = {
@@ -1964,25 +1763,6 @@
     })
   }
 
-  handleTabGroup = (index, type) => {
-    let config = JSON.parse(JSON.stringify(this.state.config))
-    
-    if (type === 'up') {
-      config.tabgroups.splice(index, 0, config.tabgroups.splice(index - 1, 1)[0])
-    } else {
-      config.tabgroups.splice(index, 0, config.tabgroups.splice(index + 1, 1)[0])
-    }
-
-    this.setState({
-      config: config
-    })
-
-    notification.success({
-      top: 92,
-      message: '璋冩暣鎴愬姛',
-      duration: 2
-    })
-  }
 
   pasteSubmit = () => {
     let _config = JSON.parse(JSON.stringify(this.state.config))
@@ -2020,13 +1800,25 @@
     })
   }
 
+  /**
+   * @description 鏇存柊鏍囩閰嶇疆淇℃伅
+   */
+  updatetabs = (config, delcards) => {
+    const { delActions } = this.state
+
+    this.setState({
+      config: config,
+      delActions: delcards ? [...delActions, ...delcards.map(item => item.uuid)] : delActions
+    })
+  }
+
   render () {
     const { config, modaltype, activeKey } = this.state
     let _length = config.groups.length
 
     let configTabs = []
-    this.state.config.tabgroups.forEach(group => {
-      configTabs.push(...this.state.config[group])
+    config.tabgroups.forEach(group => {
+      configTabs.push(...group.sublist)
     })
 
     return (
@@ -2196,30 +1988,13 @@
                 />
               </div>
               {/* 鏍囩缁� */}
-              {this.state.config.tabgroups.map((groupId, index) => {
-                return (
-                  <div key={index} className="tab-list">
-                    {index === 0 ? <Tooltip placement="bottomLeft" overlayClassName="middle" title="鍦ㄥ乏渚у伐鍏锋爮銆婃爣绛鹃〉銆嬩腑锛岄�夋嫨瀵瑰簲绫诲瀷鐨勬爣绛鹃〉鎷栬嚦姝ゅ娣诲姞銆�">
-                      <Icon type="question-circle" />
-                    </Tooltip> : null}
-                    {index !== (this.state.config.tabgroups.length - 1) ?
-                      <Icon type="arrow-down" onClick={() => {this.handleTabGroup(index, 'down')}} /> : null
-                    }
-                    {index !== 0 ? <Icon type="arrow-up" onClick={() => {this.handleTabGroup(index, 'up')}} /> : null}
-                    {index === 0 ? <Icon type="plus" onClick={this.addTabGroup} /> : null}
-                    {index !== 0 ? <Icon type="delete" onClick={() => {this.delTabGroup(groupId)}} /> : null}
-                    <TabDragElement
-                      type="tabs"
-                      groupId={groupId}
-                      list={this.state.config[groupId]}
-                      handleList={this.handleList}
-                      handleMenu={this.handleTab}
-                      deleteMenu={this.deleteElement}
-                      doubleClickCard={(tab) => this.setSubConfig(tab, 'tab')}
-                      placeholder={this.state.dict['header.form.tab.placeholder']}
-                    />
-                  </div>)
-              })}
+              <TabsComponent
+                type="formtab"
+                config={config}
+                tabs={this.state.tabviews}
+                setSubConfig={(item) => this.setSubConfig(item, 'tab')}
+                updatetabs={this.updatetabs}
+              />
             </Card>
           </div>
         </DndProvider>
@@ -2265,26 +2040,6 @@
             formlist={this.state.formlist}
             inputSubmit={this.handleSubmit}
             wrappedComponentRef={(inst) => this.actionFormRef = inst}
-          />
-        </Modal>
-        {/* 鏍囩缂栬緫 */}
-        <Modal
-          title={this.state.dict['header.modal.tabs.edit']}
-          visible={modaltype === 'tabs'}
-          width={700}
-          maskClosable={false}
-          onOk={this.handleSubmit}
-          onCancel={this.editModalCancel}
-          destroyOnClose
-        >
-          <TabForm
-            type="tabs"
-            dict={this.state.dict}
-            card={this.state.card}
-            tabs={this.state.tabviews}
-            formlist={this.state.formlist}
-            inputSubmit={this.handleSubmit}
-            wrappedComponentRef={(inst) => this.tabsFormRef = inst}
           />
         </Modal>
         {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
diff --git a/src/templates/formtabconfig/source.jsx b/src/templates/formtabconfig/source.jsx
index 962016e..aa8584d 100644
--- a/src/templates/formtabconfig/source.jsx
+++ b/src/templates/formtabconfig/source.jsx
@@ -92,31 +92,27 @@
         class: 'border-danger'
       }
     ],
-    tabs: [
-      {
-        origin: true,          // 鏄惁涓虹ず渚�
-        groupId: 'tabs',
-        uuid: Utils.getuuid(),
-        label: 'tab1',
-        icon: '',
-        type: 'SubTable',
-        linkTab: '',
-        subtabs: [],
-        supMenu: ''
-      },
-      {
-        origin: true,
-        groupId: 'tabs',
-        uuid: Utils.getuuid(),
-        label: 'tab2',
-        icon: '',
-        type: 'SubTable',
-        linkTab: '',
-        subtabs: [],
-        supMenu: ''
-      }
-    ],
-    tabgroups: ['tabs']
+    tabgroups: [{
+      uuid: 'tabs',
+      sublist: [
+        {
+          origin: true,          // 鏄惁涓虹ず渚�
+          uuid: Utils.getuuid(),
+          label: 'tab1',
+          type: 'SubTable',
+          linkTab: '',
+          supMenu: ''
+        },
+        {
+          origin: true,
+          uuid: Utils.getuuid(),
+          label: 'tab2',
+          type: 'SubTable',
+          linkTab: '',
+          supMenu: ''
+        }
+      ]
+    }]
   }
 
   searchItems = [
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index 5ab5758..43ee854 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -833,6 +833,15 @@
     }
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
   render() {
     const { config } = this.props
     const { actionlist, visible, card, dict, copying, profVisible } = this.state
diff --git a/src/templates/zshare/chartcompile/index.jsx b/src/templates/sharecomponent/chartcomponent/chartcompile/index.jsx
similarity index 100%
rename from src/templates/zshare/chartcompile/index.jsx
rename to src/templates/sharecomponent/chartcomponent/chartcompile/index.jsx
diff --git a/src/templates/zshare/chartcompile/index.scss b/src/templates/sharecomponent/chartcomponent/chartcompile/index.scss
similarity index 100%
rename from src/templates/zshare/chartcompile/index.scss
rename to src/templates/sharecomponent/chartcomponent/chartcompile/index.scss
diff --git a/src/templates/zshare/chartcomponent/index.jsx b/src/templates/sharecomponent/chartcomponent/index.jsx
similarity index 86%
rename from src/templates/zshare/chartcomponent/index.jsx
rename to src/templates/sharecomponent/chartcomponent/index.jsx
index 08359f5..c6ed3ee 100644
--- a/src/templates/zshare/chartcomponent/index.jsx
+++ b/src/templates/sharecomponent/chartcomponent/index.jsx
@@ -4,19 +4,20 @@
 import { Chart } from '@antv/g2'
 import DataSet from '@antv/data-set'
 
-import ChartDrawerForm from '@/templates/zshare/chartcompile'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import ChartDrawerForm from './chartcompile'
 import './index.scss'
 
 class LineChart extends Component {
   static propTpyes = {
-    type: PropTypes.string,
-    dict: PropTypes.object,
     plot: PropTypes.object,
-    columns: PropTypes.array,
+    config: PropTypes.object,
     plotchange: PropTypes.func
   }
 
   state = {
+    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
     visible: true
   }
 
@@ -33,12 +34,12 @@
   }
 
   getdata = (X_axis, Y_axis) => {
-    const { type } = this.props
+    const { plot } = this.props
     let data = []
     let xdata = ['鍛ㄤ竴', '鍛ㄤ簩', '鍛ㄤ笁', '鍛ㄥ洓', '鍛ㄤ簲', '鍛ㄥ叚', '鍛ㄦ棩']
     let point = 7
 
-    if (type === 'pie') {
+    if (plot.chartType === 'pie') {
       xdata = ['浜嬩緥涓�', '浜嬩緥浜�', '浜嬩緥涓�', '浜嬩緥鍥�', '浜嬩緥浜�']
       point = 5
     }
@@ -63,22 +64,22 @@
   }
 
   viewrender = () => {
-    const { type } = this.props
+    const { plot } = this.props
 
-    if (type === 'line') {
+    if (plot.chartType === 'line') {
       this.linerender()
-    } else if (type === 'bar') {
+    } else if (plot.chartType === 'bar') {
       this.barrender()
-    } else if (type === 'pie') {
+    } else if (plot.chartType === 'pie') {
       this.pierender()
     }
   }
 
   linerender = () => {
-    const { plot, columns } = this.props
+    const { plot, config } = this.props
 
     let transfield = {}
-    columns.forEach(col => {
+    config.columns.forEach(col => {
       if (col.field) {
         transfield[col.field] = col.label
       }
@@ -179,10 +180,10 @@
   }
 
   barrender = () => {
-    const { plot, columns } = this.props
+    const { plot, config } = this.props
 
     let transfield = {}
-    columns.forEach(col => {
+    config.columns.forEach(col => {
       if (col.field) {
         transfield[col.field] = col.label
       }
@@ -279,10 +280,10 @@
   }
 
   pierender = () => {
-    const { plot, columns } = this.props
+    const { plot, config } = this.props
 
     let transfield = {}
-    columns.forEach(col => {
+    config.columns.forEach(col => {
       if (col.field) {
         transfield[col.field] = col.label
       }
@@ -416,18 +417,33 @@
   }
 
   plotChange = (values) => {
-    const { plot } = this.props
+    const { plot, config } = this.props
+    let _plot = {...plot, ...values}
+    let _charts = fromJS(config.charts).toJS()
 
-    this.props.plotchange({...plot, ...values})
+    _charts = _charts.map(item => {
+      if (item.uuid === _plot.uuid) {
+        if (!is(fromJS(item), fromJS(_plot))) {
+          let _element = document.getElementById(_plot.uuid)
+          if (_element) {
+            _element.innerHTML = ''
+          }
+        }
+        return _plot
+      }
+      return item
+    })
+
+    this.props.plotchange({...config, charts: _charts})
   }
 
   render() {
-    const { plot, type } = this.props
+    const { plot } = this.props
 
     return (
       <div className="line-chart-edit-box" style={{minHeight: plot.height ? plot.height + 50 : 450}}>
         <p className="chart-title">{plot.title}</p>
-        <ChartDrawerForm type={type} columns={this.props.columns} dict={this.props.dict} plot={plot} plotchange={this.plotChange} />
+        <ChartDrawerForm type={plot.chartType} columns={this.props.config.columns} dict={this.state.dict} plot={plot} plotchange={this.plotChange} />
         <div className="canvas" id={plot.uuid}></div>
       </div>
     )
diff --git a/src/templates/zshare/chartcomponent/index.scss b/src/templates/sharecomponent/chartcomponent/index.scss
similarity index 100%
rename from src/templates/zshare/chartcomponent/index.scss
rename to src/templates/sharecomponent/chartcomponent/index.scss
diff --git a/src/templates/sharecomponent/chartgroupcomponent/index.jsx b/src/templates/sharecomponent/chartgroupcomponent/index.jsx
index eef7f36..1ed99b7 100644
--- a/src/templates/sharecomponent/chartgroupcomponent/index.jsx
+++ b/src/templates/sharecomponent/chartgroupcomponent/index.jsx
@@ -190,6 +190,14 @@
     this.props.updatechartgroup(config, id)
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
 
   render() {
     const { config } = this.props
@@ -208,7 +216,7 @@
           handleMenu={this.handleChart}
           deleteMenu={this.deletechart}
         /> : null}
-        {/* 鍚堝苟鍒楃紪杈� */}
+        {/* 鍥捐〃淇℃伅缂栬緫 */}
         <Modal
           title={modaltype === 'addChart' ? '鍥捐〃-娣诲姞' : '鍥炬爣-缂栬緫'}
           visible={modaltype === 'addChart' || modaltype === 'editChart'}
diff --git a/src/templates/sharecomponent/columncomponent/index.jsx b/src/templates/sharecomponent/columncomponent/index.jsx
index aa07790..10940fb 100644
--- a/src/templates/sharecomponent/columncomponent/index.jsx
+++ b/src/templates/sharecomponent/columncomponent/index.jsx
@@ -350,6 +350,15 @@
     })
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
   render() {
     const { config } = this.props
     const { modaltype, columnlist, dict, card } = this.state
diff --git a/src/templates/sharecomponent/fieldscomponent/index.jsx b/src/templates/sharecomponent/fieldscomponent/index.jsx
index 31db78f..e83eded 100644
--- a/src/templates/sharecomponent/fieldscomponent/index.jsx
+++ b/src/templates/sharecomponent/fieldscomponent/index.jsx
@@ -205,6 +205,14 @@
     }
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
 
   render() {
     const { type } = this.props
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index fa84f28..c0cdff2 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -237,6 +237,15 @@
     })
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
   render() {
     const { dict, searchlist, visible, sqlVerifing, card } = this.state
 
diff --git a/src/templates/sharecomponent/settingcomponent/index.jsx b/src/templates/sharecomponent/settingcomponent/index.jsx
index b14b612..1bae607 100644
--- a/src/templates/sharecomponent/settingcomponent/index.jsx
+++ b/src/templates/sharecomponent/settingcomponent/index.jsx
@@ -156,6 +156,15 @@
     })
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
   render() {
     const { config, type } = this.props
     const { dict, visible } = this.state
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index bcf1a37..4277f06 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -231,6 +231,15 @@
     this.props.updatetable({...config, tables: _tables}, _fields)
   }
 
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
   render() {
     const { containerId } = this.props
     const { dict, tables, selectedTables } = this.state
diff --git a/src/templates/sharecomponent/tabscomponent/index.jsx b/src/templates/sharecomponent/tabscomponent/index.jsx
new file mode 100644
index 0000000..69bf3e2
--- /dev/null
+++ b/src/templates/sharecomponent/tabscomponent/index.jsx
@@ -0,0 +1,383 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Icon, Tooltip, Modal, notification } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import { getTabForm } from '@/templates/zshare/formconfig'
+
+import TabForm from './tabform'
+import TabDragElement from './tabdragelement'
+import './index.scss'
+
+const { confirm } = Modal
+
+// **鎮茶鑰呭線寰�姝g‘锛屼箰瑙傝�呭線寰�鎴愬姛
+class TablesComponent extends Component {
+  static propTpyes = {
+    type: PropTypes.string,       // 鑿滃崟绫诲瀷
+    tabs: PropTypes.array,        // 鏍囩缁�
+    config: PropTypes.object,     // 椤甸潰閰嶇疆
+    setSubConfig: PropTypes.func, // 瀛愭爣绛鹃厤缃�
+    updatetabs: PropTypes.func    // 鏇存柊鏍囩缁勮缃�
+  }
+
+  state = {
+    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
+    tabgroups: [],     // 鏍囩缁�
+    card: [],          // 缂栬緫鏍囩
+    group: [],         // 缂栬緫缁�
+    visible: false     // 妯℃�佹鎺у埗
+  }
+
+  /**
+   * @description 鏍囩缁勫垵濮嬪寲
+   */
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    this.setState({
+      tabgroups: fromJS(config.tabgroups).toJS()
+    })
+  }
+
+  /**
+   * @description 鍏冪礌娣诲姞鎴栨嫋鍔ㄦ椂椤哄簭鍙樺寲
+   */
+  handleList = (list, card, groupId) => {
+    const { config } = this.props
+    let _tabgroups = fromJS(this.state.tabgroups).toJS()
+    let _group = null
+    
+    _tabgroups = _tabgroups.map(group => {
+      if (group.uuid === groupId) {
+        group.sublist = list
+        _group = fromJS(group).toJS()
+      }
+      return group
+    })
+
+    if (card) {
+      this.setState({tabgroups: _tabgroups})
+      this.handleTab(card, _group)
+    } else {
+      this.setState({tabgroups: _tabgroups})
+      this.props.updatetabs({...config, tabgroups: _tabgroups})
+    }
+  }
+
+  /**
+   * @description 鏍囩缂栬緫锛岀瓫閫夊彲閫夌殑涓嬬骇鏍囩涓庡凡鍏宠仈鐨勪笅绾ф爣绛�
+   */
+  handleTab = (card, _group) => {
+    let tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    let menus = [
+      {value: '', text: '绌�'},
+      {value: 'mainTable', text: this.props.type === 'main' ? '涓昏〃' : '涓绘暟鎹�'}
+    ]
+    let equalTabs = []
+    let supMenu = card.supMenu || ''
+    let equalTab = card.equalTab || []
+    let isuptab = true
+    let equalTabIds = []
+
+    tabgroups.forEach((group, i) => {
+      if (group.uuid === _group.uuid) {
+        isuptab = false
+        group.sublist.forEach(tab => { // 鍙叧鑱旂殑鍚岀骇鏍囩
+          if (tab.uuid === card.uuid) return
+
+          equalTabIds.push(tab.uuid)
+          equalTabs.push(tab)
+        })
+      } else if (isuptab) {
+        group.sublist.forEach(tab => {
+          menus.push({
+            value: tab.uuid,
+            text: tab.label
+          })
+        })
+      }
+    })
+
+    if (supMenu && menus.filter(menu => menu.value === supMenu).length === 0) {
+      supMenu = ''
+    }
+
+    if (equalTab.length > 0) {
+      equalTab = equalTab.filter(tabId => equalTabIds.includes(tabId))
+    }
+
+    this.setState({
+      visible: true,
+      card: card,
+      group: _group,
+      formlist: getTabForm(card, supMenu, menus, equalTab, equalTabs, this.props.type)
+    })
+  }
+
+  /**
+   * @description 鏍囩淇敼鍚庢彁浜や繚瀛�
+   */
+  handleSubmit = () => {
+    const { config } = this.props
+    const { group, card } = this.state
+    let tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    this.tabsFormRef.handleConfirm().then(res => {
+      if (tabgroups.length === 1) {
+        tabgroups.forEach(_group => {
+          _group.sublist = _group.sublist.filter(item => !item.origin || item.uuid === card.uuid)
+        })
+      }
+
+      let tabnames = []
+      tabgroups.forEach(_group => {
+        _group.sublist.forEach(item => {
+          if (item.uuid !== card.uuid) {
+            tabnames.push(item.label)
+          }
+        })
+      })
+
+      if (tabnames.includes(res.label)) {
+        notification.warning({
+          top: 92,
+          message: '鏍囩銆�' + res.label + '銆嬪凡瀛樺湪锛�',
+          duration: 5
+        })
+        return
+      }
+
+      tabgroups = tabgroups.map(_group => {
+        if (_group.uuid === group.uuid) {
+          _group.sublist = _group.sublist.map(item => {
+            if (item.uuid === card.uuid) {
+              return res
+            } else {
+              return item
+            }
+          })
+        }
+        return _group
+      })
+
+      this.setState({
+        card: null,
+        group: null,
+        tabgroups: tabgroups, 
+        visible: false
+      })
+      this.props.updatetabs({...config, tabgroups: tabgroups})
+    })
+  }
+  
+  /**
+   * @description 鍒犻櫎鏍囩
+   */
+  deleteElement = (card, group) => {
+    const { config } = this.props
+    let _this = this
+    let tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    confirm({
+      content: `纭畾鍒犻櫎<<${card.label}>>鍚楋紵`,
+      okText: this.state.dict['model.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+        tabgroups = tabgroups.map(_group => {
+          if (_group.uuid === group.uuid) {
+            _group.sublist = _group.sublist.filter(item => item.uuid !== card.uuid)
+          }
+          return _group
+        })
+
+        _this.setState({
+          tabgroups: tabgroups
+        })
+        _this.props.updatetabs({...config, tabgroups: tabgroups}, [card])
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 澧炲姞鏍囩椤靛垎缁�
+   */
+  addTabGroup = () => {
+    const { config } = this.props
+    let _this = this
+    let _tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    confirm({
+      content: `纭畾鏂板缓鏍囩缁勫悧锛焋,
+      okText: this.state.dict['model.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+        if (_tabgroups.length === 1) {
+          _tabgroups.forEach(group => {
+            group.sublist = group.sublist.filter(item => !item.origin)
+          })
+        }
+
+        _tabgroups.push({
+          uuid: Utils.getuuid(),
+          sublist:[]
+        })
+
+        _this.setState({
+          tabgroups: _tabgroups
+        })
+        _this.props.updatetabs({...config, tabgroups: _tabgroups})
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 鍒犻櫎鏍囩椤靛垎缁�
+   */
+  delTabGroup = (group) => {
+    const { config } = this.props
+    let _this = this
+    let _tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    confirm({
+      content: `纭畾鍒犻櫎鏍囩缁勫悧锛焋,
+      okText: this.state.dict['model.confirm'],
+      cancelText: this.state.dict['header.cancel'],
+      onOk() {
+
+        _tabgroups = _tabgroups.filter(_group => _group.uuid !== group.uuid)
+
+        _this.setState({
+          tabgroups: _tabgroups
+        })
+        _this.props.updatetabs({...config, tabgroups: _tabgroups}, group.sublist)
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 鏍囩缁勪笂涓嬬Щ鍔�
+   */
+  handleGroup = (index, type) => {
+    const { config } = this.props
+    let _tabgroups = fromJS(this.state.tabgroups).toJS()
+    
+    if (type === 'up') {
+      _tabgroups.splice(index, 0, _tabgroups.splice(index - 1, 1)[0])
+    } else {
+      _tabgroups.splice(index, 0, _tabgroups.splice(index + 1, 1)[0])
+    }
+
+    this.setState({
+      tabgroups: _tabgroups
+    })
+    this.props.updatetabs({...config, tabgroups: _tabgroups})
+
+    notification.success({
+      top: 92,
+      message: '璋冩暣鎴愬姛',
+      duration: 2
+    })
+  }
+
+  
+  /**
+   * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎
+   */
+  editModalCancel = () => {
+    const { config } = this.props
+    const { group, card } = this.state
+    let _tabgroups = fromJS(this.state.tabgroups).toJS()
+
+    if (card && card.focus) {
+      _tabgroups = _tabgroups.map(_group => {
+        if (_group.uuid === group.uuid) {
+          _group.sublist = _group.sublist.filter(item => item.uuid !== card.uuid)
+        }
+        return _group
+      })
+
+      this.setState({
+        card: null,
+        group: null,
+        tabgroups: _tabgroups,
+        visible: false
+      })
+      this.props.updatetabs({...config, tabgroups: _tabgroups})
+    } else {
+      this.setState({
+        card: null,
+        group: null,
+        visible: false
+      })
+    }
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { tabgroups, visible, dict } = this.state
+
+    return (
+      <div className="model-table-tab-list">
+        {tabgroups.map((group, index) => {
+          return (
+            <div key={index} className="tab-line-list">
+              {index === 0 ? <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.tabs.guide']}>
+                <Icon type="question-circle" />
+              </Tooltip> : null}
+              {index !== (tabgroups.length - 1) ?
+                <Icon type="arrow-down" onClick={() => {this.handleGroup(index, 'down')}} /> : null
+              }
+              {index !== 0 ? <Icon type="arrow-up" onClick={() => {this.handleGroup(index, 'up')}} /> : null}
+              {index === 0 ? <Icon type="plus" onClick={this.addTabGroup} /> : null}
+              {index !== 0 ? <Icon type="delete" onClick={() => {this.delTabGroup(group)}} /> : null}
+              <TabDragElement
+                list={group.sublist}
+                handleList={(list, newcard) => this.handleList(list, newcard, group.uuid)}
+                handleMenu={(card) => this.handleTab(card, group)}
+                deleteMenu={(card) => this.deleteElement(card, group)}
+                doubleClickCard={this.props.setSubConfig}
+                placeholder={this.state.dict['header.form.tab.placeholder']}
+              />
+            </div>)
+        })}
+        {/* 鏍囩缂栬緫 */}
+        <Modal
+          title={this.state.dict['header.modal.tabs.edit']}
+          visible={visible}
+          width={750}
+          maskClosable={false}
+          onOk={this.handleSubmit}
+          onCancel={this.editModalCancel}
+          destroyOnClose
+        >
+          <TabForm
+            dict={this.state.dict}
+            card={this.state.card}
+            tabs={this.props.tabs}
+            formlist={this.state.formlist}
+            inputSubmit={this.handleSubmit}
+            wrappedComponentRef={(inst) => this.tabsFormRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default TablesComponent
\ No newline at end of file
diff --git a/src/templates/sharecomponent/tabscomponent/index.scss b/src/templates/sharecomponent/tabscomponent/index.scss
new file mode 100644
index 0000000..dec6c80
--- /dev/null
+++ b/src/templates/sharecomponent/tabscomponent/index.scss
@@ -0,0 +1,99 @@
+.model-table-tab-list {
+  clear: both;
+  .tab-line-list {
+    position: relative;
+    padding: 30px 20px 0px;
+    .ant-switch {
+      position: absolute;
+      right: 20px;
+      top: 20px;
+    }
+    > .ant-row {
+      min-height: 47px;
+      .page-card {
+        position: relative;
+        padding: 0px;
+        > div {
+          padding: 12px 0px 0px;
+          cursor: move;
+        }
+      }
+      .ant-tabs-tab {
+        cursor: default;
+        .edit {
+          position: absolute;
+          left: 0;
+          top: 0px;
+          color: #1890ff;
+          cursor: pointer;
+          display: none;
+        }
+        .edit.close {
+          left: 20px;
+          color: #ff4d4f;
+        }
+      }
+      .ant-tabs-bar {
+        min-height: 55px;
+      }
+      .ant-tabs-tab:hover {
+        .edit {
+          display: inline-block;
+        }
+      }
+      .ant-tabs-content {
+        .ant-tabs-tabpane img {
+          width: 100%;
+        }
+      }
+    }
+    > .anticon-question-circle {
+      color: #c49f47;
+      position: absolute;
+      left: 5px;
+      top: 20px;
+    }
+    > .anticon-plus {
+      position: absolute;
+      font-size: 18px;
+      right: 25px;
+      top: 50px;
+      z-index: 1;
+      color: #26C281;
+      cursor: pointer;
+    }
+    > .anticon-delete {
+      position: absolute;
+      font-size: 19px;
+      right: 25px;
+      top: 50px;
+      z-index: 1;
+      color: #ff4d4f;
+      cursor: pointer;
+    }
+    > .anticon-arrow-up {
+      position: absolute;
+      right: 55px;
+      font-size: 19px;
+      z-index: 1;
+      top: 50px;
+      color: #1890ff;
+      cursor: pointer;
+    }
+    > .anticon-arrow-down {
+      position: absolute;
+      right: 55px;
+      font-size: 19px;
+      z-index: 1;
+      top: 50px;
+      color: purple;
+      cursor: pointer;
+    }
+    > .anticon-arrow-down + .anticon-arrow-up {
+      right: 85px;
+    }
+    .ant-tabs-nav-container-scrolling {
+      margin-right: 50px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/templates/zshare/tabdragelement/card.jsx b/src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx
similarity index 87%
rename from src/templates/zshare/tabdragelement/card.jsx
rename to src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx
index 81ec448..bc89726 100644
--- a/src/templates/zshare/tabdragelement/card.jsx
+++ b/src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx
@@ -3,16 +3,16 @@
 import { Icon } from 'antd'
 import './index.scss'
 
-const Card = ({ id, type, card, moveCard, findCard, doubleClickCard, hasDrop }) => {
+const Card = ({ id, card, moveCard, findCard, doubleClickCard, hasDrop }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
-    item: { type: type, id, originalIndex },
+    item: { type: 'tabs', id, originalIndex },
     collect: monitor => ({
       isDragging: monitor.isDragging(),
     }),
   })
   const [, drop] = useDrop({
-    accept: type,
+    accept: 'tabs',
     canDrop: () => true,
     drop: (item) => {
       if (!item.hasOwnProperty('originalIndex')) {
diff --git a/src/templates/zshare/tabdragelement/index.jsx b/src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx
similarity index 82%
rename from src/templates/zshare/tabdragelement/index.jsx
rename to src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx
index 2d2a888..92bb326 100644
--- a/src/templates/zshare/tabdragelement/index.jsx
+++ b/src/templates/sharecomponent/tabscomponent/tabdragelement/index.jsx
@@ -9,7 +9,7 @@
 
 const { TabPane } = Tabs
 
-const Container = ({list, type, groupId, placeholder, handleList, handleMenu, deleteMenu, doubleClickCard }) => {
+const Container = ({list, placeholder, handleList, handleMenu, deleteMenu, doubleClickCard }) => {
   let target = null
   const [cards, setCards] = useState(list)
   const moveCard = (id, atIndex) => {
@@ -17,7 +17,8 @@
     if (!card) return
     
     const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
-    handleList(type, _cards, card)
+
+    handleList(_cards)
   }
 
   if (!is(fromJS(cards), fromJS(list))) {
@@ -37,7 +38,7 @@
   }
 
   const [, drop] = useDrop({
-    accept: type,
+    accept: 'tabs',
     drop(item) {
       if (item.hasOwnProperty('originalIndex')) {
         return
@@ -50,9 +51,7 @@
       newcard.icon = ''
       newcard.type = item.subType
       newcard.linkTab = ''
-      newcard.subtabs = []
       newcard.supMenu = 'mainTable'
-      newcard.groupId = groupId
       newcard.focus = true
 
       let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
@@ -66,26 +65,18 @@
       targetIndex++
 
       const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
-      handleList(type, _cards, newcard)
+      handleList(_cards, newcard)
       target = null
     }
   })
-  
-  const edit = (card) => {
-    handleMenu(card)
-  }
 
   const doubleClickBab = id => {
     const { card } = findCard(id)
     doubleClickCard(card)
   }
-  
-  const del = (card) => {
-    deleteMenu({card: card, type: type})
-  }
 
   return (
-    <div ref={drop} className="ant-row maintable-tab-list">
+    <div ref={drop} className="ant-row model-tab-drag-list">
       <Tabs defaultActiveKey="0">
         {cards.map((card, index) => (
           <TabPane tab={
@@ -93,15 +84,14 @@
               <Card
                 key={card.uuid}
                 id={`${card.uuid}`}
-                type={type}
                 card={card}
                 moveCard={moveCard}
                 findCard={findCard}
                 hasDrop={hasDrop}
                 doubleClickCard={doubleClickBab}
               />
-              <Icon className="edit" type="edit" onClick={() => edit(card)} />
-              <Icon className="edit close" type="close" onClick={() => del(card)} />
+              <Icon className="edit" type="edit" onClick={() => handleMenu(card)} />
+              <Icon className="edit close" type="close" onClick={() => deleteMenu(card)} />
             </div>
           } key={`${index}`}>
             銆妠card.label}銆嬫爣绛惧唴瀹�
diff --git a/src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss b/src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss
new file mode 100644
index 0000000..b6cd048
--- /dev/null
+++ b/src/templates/sharecomponent/tabscomponent/tabdragelement/index.scss
@@ -0,0 +1,12 @@
+.model-tab-drag-list {
+  .ant-tabs-content {
+    text-align: center;
+    color: #bcbcbc;
+  }
+  .commontab-drawarea-placeholder {
+    position: absolute;
+    top: 25px;
+    left: calc(50% - 50px);
+    color: #bcbcbc;
+  }
+}
\ No newline at end of file
diff --git a/src/templates/zshare/tabform/index.jsx b/src/templates/sharecomponent/tabscomponent/tabform/index.jsx
similarity index 98%
rename from src/templates/zshare/tabform/index.jsx
rename to src/templates/sharecomponent/tabscomponent/tabform/index.jsx
index 0f8cf4d..eb0bedf 100644
--- a/src/templates/zshare/tabform/index.jsx
+++ b/src/templates/sharecomponent/tabscomponent/tabform/index.jsx
@@ -9,7 +9,6 @@
 class MainTab extends Component {
   static propTpyes = {
     tabs: PropTypes.array,       // 鍙叧鑱旀爣绛鹃泦
-    type: PropTypes.string,      // 绫诲瀷
     dict: PropTypes.object,      // 瀛楀吀椤�
     formlist: PropTypes.any,     // 琛ㄥ崟
     card: PropTypes.object,      // 鏍囩椤典俊鎭�
@@ -110,7 +109,7 @@
     const fields = []
     
     this.state.formlist.forEach((item, index) => {
-      if (item.hidden) return
+      if (item.hidden || item.forbid) return
 
       if (item.type === 'text') { // 鏂囨湰鎼滅储
         let rules = []
@@ -245,7 +244,6 @@
         if (!err) {
 
           values.uuid = this.props.card.uuid
-          values.groupId = this.props.card.groupId
 
           if (!values.linkTab) { // 娌℃湁鍏宠仈鏍囩锛堟柊寤烘椂锛夛紝鍒涘缓鏂版爣绛綢d
             values.linkTab = Utils.getuuid()
diff --git a/src/templates/zshare/tabform/index.scss b/src/templates/sharecomponent/tabscomponent/tabform/index.scss
similarity index 100%
rename from src/templates/zshare/tabform/index.scss
rename to src/templates/sharecomponent/tabscomponent/tabform/index.scss
diff --git a/src/templates/subtableconfig/index.jsx b/src/templates/subtableconfig/index.jsx
index 5ee3d8c..2747162 100644
--- a/src/templates/subtableconfig/index.jsx
+++ b/src/templates/subtableconfig/index.jsx
@@ -20,11 +20,11 @@
 import SearchComponent from '@/templates/sharecomponent/searchcomponent'
 import ActionComponent from '@/templates/sharecomponent/actioncomponent'
 import ColumnComponent from '@/templates/sharecomponent/columncomponent'
+import ChartComponent from '@/templates/sharecomponent/chartcomponent'
 
 import MenuForm from '@/templates/zshare/menuform'
 import EditComponent from '@/templates/zshare/editcomponent'
 import SourceElement from '@/templates/zshare/dragsource'
-import ChartComponent from '@/templates/zshare/chartcomponent'
 import Source from './source'
 import './index.scss'
 
@@ -739,7 +739,7 @@
       })
     } else {
       this.menuformRef.handleConfirm().then(res => {
-        let _config = {...config, ...res}
+        let _config = {...config, tabName: res.MenuName, tabNo: res.MenuNo, Remark: res.Remark}
 
         if (!is(fromJS(originConfig), fromJS(_config))) {
           this.setState({
@@ -771,7 +771,7 @@
       })
     } else {
       this.menuformRef.handleConfirm().then(res => {
-        let _config = {...config, ...res}
+        let _config = {...config, tabName: res.MenuName, tabNo: res.MenuNo, Remark: res.Remark}
 
         if (!is(fromJS(originConfig), fromJS(_config))) {
           notification.warning({
@@ -905,31 +905,6 @@
         })
       })
     }
-  }
-
-  /**
-   * @description 鍥捐〃閰嶇疆淇敼鍚庝繚瀛�
-   */
-  updateChart = (plot) => {
-    const { config } = this.state
-    let _charts = JSON.parse(JSON.stringify(config.charts))
-
-    _charts = _charts.map(item => {
-      if (item.uuid === plot.uuid) {
-        if (!is(fromJS(item), fromJS(plot))) {
-          let _element = document.getElementById(plot.uuid)
-          if (_element) {
-            _element.innerHTML = ''
-          }
-        }
-        return plot
-      }
-      return item
-    })
-
-    this.setState({
-      config: {...config, charts: _charts}
-    })
   }
 
   /**
@@ -1152,11 +1127,9 @@
                     return (
                       <Col span={item.width} key={item.uuid}>
                         <ChartComponent
-                          type={item.chartType}
-                          dict={this.state.dict}
-                          columns={config.columns}
-                          plotchange={this.updateChart}
                           plot={item}
+                          config={config}
+                          plotchange={this.updateconfig}
                         />
                       </Col>
                     )
diff --git a/src/templates/subtableconfig/settingform/index.jsx b/src/templates/subtableconfig/settingform/index.jsx
deleted file mode 100644
index 84b34e4..0000000
--- a/src/templates/subtableconfig/settingform/index.jsx
+++ /dev/null
@@ -1,352 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Radio, Select, Tooltip, Icon, notification } from 'antd'
-import { formRule } from '@/utils/option.js'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const { TextArea } = Input
-
-class SettingForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object, // 瀛楀吀椤�
-    tabId: PropTypes.string,
-    data: PropTypes.object,
-    columns: PropTypes.array,
-    usefulFields: PropTypes.array,
-    inputSubmit: PropTypes.any     // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    interType: this.props.data.interType || 'inner',
-    columns: this.props.columns.filter(item => item.field && item.type !== 'colspan'),
-    interReadonly: this.props.data.sysInterface === 'true',
-    primaryKey: ''
-  }
-
-  UNSAFE_componentWillMount() {
-    const { data, columns } = this.props
-
-    let primaryKey = data.primaryKey
-    if (primaryKey) {
-      let field = columns.filter(column => column.field === primaryKey)
-      if (field.length !== 1) {
-        primaryKey = ''
-      }
-    }
-    if (!primaryKey) {
-      columns.forEach(col => {
-        if (col.field.toLowerCase() === 'id') {
-          primaryKey = col.field
-        }
-      })
-    }
-
-    this.setState({
-      primaryKey: primaryKey
-    })
-  }
-
-  handleConfirm = () => {
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          values.actionfixed = values.actionfixed === 'true'
-          values.columnfixed = values.columnfixed === 'true'
-
-          if (values.interType === 'inner' && !values.innerFunc && !values.dataresource) {
-            notification.warning({
-              top: 92,
-              message: '璇疯嚜瀹氫箟鍑芥暟鎴栧~鍐欐暟鎹簮锛�',
-              duration: 5
-            })
-          } else {
-            let error = Utils.verifySql(values.dataresource)
-
-            if (error) {
-              notification.warning({
-                top: 92,
-                message: '鏁版嵁婧愪腑涓嶅彲浣跨敤' + error,
-                duration: 5
-              })
-              return
-            }
-
-            resolve(values)
-          }
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  /**
-   * @description 鍒囨崲鎺ュ彛绫诲瀷
-   */
-  onChange = (e) => {
-    this.setState({
-      interType: e.target.value
-    }, () => {
-      if (e.target.value === 'inner') return
-
-      let _type = this.props.form.getFieldValue('sysInterface')
-      if (_type === 'true') {
-        this.props.form.setFieldsValue({
-          interface: window.GLOB.mainSystemApi || ''
-        })
-        this.setState({
-          interReadonly: true
-        })
-      } else {
-        this.setState({
-          interReadonly: false
-        })
-      }
-    })
-  }
-
-  onSysChange = (e) => {
-    if (e.target.value === 'true') {
-      this.props.form.setFieldsValue({
-        interface: window.GLOB.mainSystemApi || ''
-      })
-      this.setState({
-        interReadonly: true
-      })
-    } else {
-      this.setState({
-        interReadonly: false
-      })
-    }
-  }
-
-  selectChange = (val) => {
-    this.props.form.setFieldsValue({
-      order: `${val} desc`
-    })
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  render() {
-    const { data, dict, tabId, usefulFields } = this.props
-    const { getFieldDecorator } = this.props.form
-    const { interType, columns, primaryKey } = this.state
-
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 8 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 16 }
-      }
-    }
-
-    let str = '^(' + usefulFields.join('|') + ')'
-    let _patten = new RegExp(str + formRule.func.innerPattern + '$', 'g')
-
-    return (
-      <Form {...formItemLayout} className="ant-advanced-search-form subtable-setting-form" id="subtable-setting-form">
-        <Row gutter={24}>
-          <Col span={12}>
-            <Form.Item label="琛ㄥ悕">
-              {getFieldDecorator('tableName', {
-                initialValue: data.tableName || '',
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '琛ㄥ悕!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="琛ㄦ牸灞炴��">
-              {getFieldDecorator('tableType', {
-                initialValue: data.tableType || 'checkbox'
-              })(
-                <Select
-                  getPopupContainer={() => document.getElementById('subtable-setting-form')}
-                >
-                  <Select.Option value="">涓嶅彲閫�</Select.Option>
-                  <Select.Option value="radio">鍗曢��</Select.Option>
-                  <Select.Option value="checkbox">澶氶��</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label={dict['header.form.intertype']}>
-              {getFieldDecorator('interType', {
-                initialValue: data.interType || 'inner'
-              })(
-                <Radio.Group onChange={this.onChange}>
-                  <Radio value="inner">{dict['header.form.interface.inner']}</Radio>
-                  <Radio value="outer">{dict['header.form.interface.outer']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.sysInterface']}>
-              {getFieldDecorator('sysInterface', {
-                initialValue: data.sysInterface || 'false'
-              })(
-                <Radio.Group onChange={this.onSysChange}>
-                  <Radio value="true">{dict['header.form.true']}</Radio>
-                  <Radio value="false">{dict['header.form.false']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.interface']}>
-              {getFieldDecorator('interface', {
-                initialValue: data.sysInterface === 'true' ? (window.GLOB.mainSystemApi || '') : (data.interface || ''),
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + dict['header.form.interface'] + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={this.state.interReadonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType === 'outer' ? <Col span={12}>
-            <Form.Item label={dict['header.form.outerFunc']}>
-              {getFieldDecorator('outerFunc', {
-                initialValue: data.outerFunc || '',
-                rules: [
-                  {
-                    pattern: formRule.func.pattern,
-                    message: formRule.func.message
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" overlayClassName="middle" title={`鍙嚜瀹氫箟鏁版嵁澶勭悊鍑芥暟锛屽嚱鏁板悕绉伴渶浠�${usefulFields.join(', ')}绛夊瓧绗﹀紑濮嬶紱鏈缃椂浼氳皟鐢ㄧ郴缁熷嚱鏁帮紝浣跨敤绯荤粺鍑芥暟闇�瀹屽杽鏁版嵁婧愩�俙}>
-                <Icon type="question-circle" />
-                {dict['header.form.innerFunc']}
-              </Tooltip>
-            }>
-              {getFieldDecorator('innerFunc', {
-                initialValue: data.innerFunc || '',
-                rules: [
-                  {
-                    pattern: _patten,
-                    message: formRule.func.innerMessage
-                  }, {
-                    max: formRule.func.max,
-                    message: formRule.func.maxMessage
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={24}>
-            <Form.Item help={'鏁版嵁ID锛�' + tabId} label={
-              <Tooltip placement="topLeft" title="浣跨敤绯荤粺鍑芥暟鏃讹紝闇�濉啓鏁版嵁婧愶紝鑷畾涔夊嚱鏁版椂锛屽彲蹇界暐銆�">
-                <Icon type="question-circle" />
-                {'鏁版嵁婧�'}
-              </Tooltip>
-            } className="textarea">
-              {getFieldDecorator('dataresource', {
-                initialValue: data.dataresource || ''
-              })(<TextArea rows={4} />)}
-            </Form.Item>
-          </Col> : null}
-          {interType !== 'outer' ? <Col span={12}>
-            <Form.Item label={
-              <Tooltip placement="topLeft" title="鏌ヨ鏃讹紝鎼滅储鏉′欢浠here鏉′欢鎷兼帴杩涘叆sql锛岀粺璁℃椂锛屽皢鏁版嵁婧愪腑浠モ�淍+鎼滅储瀛楁鈥濈殑鍐呭锛屼互鎼滅储鏉′欢涓殑鍊艰繘琛屾浛鎹㈠悗锛屾彁浜ゆ煡璇紝娉細鏌ヨ绫诲瀷浠呭湪浣跨敤绯荤粺鍑芥暟鏃舵湁鏁堛��">
-                <Icon type="question-circle" />
-                {dict['header.form.queryType']}
-              </Tooltip>
-            }>
-              {getFieldDecorator('queryType', {
-                initialValue: data.queryType || 'query'
-              })(
-                <Radio.Group>
-                  <Radio value="query">{dict['header.form.query']}</Radio>
-                  <Radio value="statistics">{dict['header.form.statistics']}</Radio>
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col> : null}
-          <Col span={12}>
-            <Form.Item label="涓婚敭">
-              {getFieldDecorator('primaryKey', {
-                initialValue: primaryKey || ''
-              })(
-                <Select
-                  getPopupContainer={() => document.getElementById('subtable-setting-form')}
-                  onChange={this.selectChange}
-                >
-                  <Select.Option key='unset' value="">鏈缃�</Select.Option>
-                  {columns.map((option, index) =>
-                    <Select.Option id={option.uuid} title={option.label} key={index} value={option.field}>{option.label}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="榛樿鎺掑簭">
-              {getFieldDecorator('order', {
-                initialValue: data.order || (primaryKey ? primaryKey + ' desc' : ''),
-                rules: [
-                  {
-                    required: true,
-                    message: dict['form.required.input'] + '榛樿鎺掑簭瀛楁!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="ID asc, UID desc" autoComplete="off" onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="鍒濆鍖�">
-              {getFieldDecorator('onload', {
-                initialValue: data.onload || 'true'
-              })(
-                <Select>
-                  <Select.Option value="true">鍔犺浇鏁版嵁</Select.Option>
-                  <Select.Option value="false">涓嶅姞杞芥暟鎹�</Select.Option>
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/templates/subtableconfig/settingform/index.scss b/src/templates/subtableconfig/settingform/index.scss
deleted file mode 100644
index 1024b34..0000000
--- a/src/templates/subtableconfig/settingform/index.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-.ant-advanced-search-form.subtable-setting-form {
-  .textarea {
-    .ant-form-item-label {
-      width: 16.3%;
-    }
-    .ant-form-item-control-wrapper {
-      width: 83.33333333%;
-    }
-  }
-  .anticon-question-circle {
-    color: #c49f47;
-    margin-right: 3px;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/zshare/chartform/index.jsx b/src/templates/zshare/chartform/index.jsx
deleted file mode 100644
index 0d0c26d..0000000
--- a/src/templates/zshare/chartform/index.jsx
+++ /dev/null
@@ -1,379 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon } from 'antd'
-
-import { formRule } from '@/utils/option.js'
-import line1 from '@/assets/img/line1.png'
-import line2 from '@/assets/img/line2.png'
-import line3 from '@/assets/img/line3.png'
-import line4 from '@/assets/img/line4.png'
-import bar1 from '@/assets/img/bar1.png'
-import bar2 from '@/assets/img/bar2.png'
-import bar3 from '@/assets/img/bar3.png'
-import bar4 from '@/assets/img/bar4.png'
-import pie1 from '@/assets/img/pie1.png'
-import pie2 from '@/assets/img/pie2.png'
-import './index.scss'
-
-const syslegends = {
-  line: [
-    {
-      uuid: 'line1',
-      url: line1,
-      options: {
-        shape: 'line',
-        coordinate: 'angle'
-      }
-    },
-    {
-      uuid: 'line2',
-      url: line2,
-      options: {
-        shape: 'smooth',
-        coordinate: 'angle'
-      }
-    },
-    {
-      uuid: 'line3',
-      url: line3,
-      options: {
-        shape: 'hv',
-        coordinate: 'angle'
-      }
-    },
-    {
-      uuid: 'line4',
-      url: line4,
-      options: {
-        shape: 'smooth',
-        coordinate: 'polar'
-      }
-    }
-  ],
-  bar: [
-    {
-      uuid: 'bar1',
-      url: bar1,
-      options: {
-        shape: 'rect',
-        adjust: 'dodge',
-        transpose: 'false'
-      }
-    },
-    {
-      uuid: 'bar2',
-      url: bar2,
-      options: {
-        shape: 'rect',
-        adjust: 'dodge',
-        transpose: 'false'
-      }
-    },
-    {
-      uuid: 'bar3',
-      url: bar3,
-      options: {
-        shape: 'rect',
-        adjust: 'stack',
-        transpose: 'false'
-      }
-    },
-    {
-      uuid: 'bar4',
-      url: bar4,
-      options: {
-        shape: 'rect',
-        adjust: 'dodge',
-        transpose: 'true'
-      }
-    }
-  ],
-  pie: [
-    {
-      uuid: 'pie1',
-      url: pie1,
-      options: {
-        shape: 'pie'
-      }
-    },
-    {
-      uuid: 'pie2',
-      url: pie2,
-      options: {
-        shape: 'ring'
-      }
-    }
-  ]
-}
-
-class ChartForm extends Component {
-  static propTpyes = {
-    dict: PropTypes.object,     // 瀛楀吀椤�
-    MenuID: PropTypes.any,
-    formlist: PropTypes.any,
-    card: PropTypes.any,
-    inputSubmit: PropTypes.any  // 鍥炶溅鎻愪氦浜嬩欢
-  }
-
-  state = {
-    formlist: null,
-    legends: null,
-    selectlegend: null
-  }
-
-  UNSAFE_componentWillMount () {
-    const { card } = this.props
-
-    let _type = card.chartType || 'line'
-    let _legends = null
-    let _selectlegend = null
-
-    if (_type === 'line' || _type === 'bar' || _type === 'line') {
-      _legends = syslegends[_type]
-      _selectlegend = _legends.filter(item => item.uuid === card.modelId)[0]
-
-      if (!_selectlegend) {
-        _selectlegend = _legends[0]
-      }
-    }
-
-    this.setState({
-      legends: _legends,
-      selectlegend: _selectlegend
-    })
-  }
-
-  componentDidMount () {
-    const { card } = this.props
-
-    if (!card.chartType) {
-      try {
-        let _form = document.getElementById('title')
-        _form.select()
-      } catch {
-        console.warn('琛ㄥ崟focus澶辫触锛�')
-      }
-    }
-  }
-
-  handleSubmit = (e) => {
-    e.preventDefault()
-
-    if (this.props.inputSubmit) {
-      this.props.inputSubmit()
-    }
-  }
-
-  typeChange = (key, value) => {
-    if (key === 'chartType') {
-      this.setState({
-        legends: syslegends[value] || null,
-        selectlegend: syslegends[value][0]
-      })
-    }
-  }
-
-  changeSelectLegend = (item) => {
-    this.setState({
-      selectlegend: item
-    })
-  }
-
-  getFields() {
-    const { getFieldDecorator } = this.props.form
-    const fields = []
-    this.props.formlist.forEach((item, index) => {
-      if (item.hidden) return
-      
-      if (item.type === 'text') { // 鏂囨湰鎼滅储
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <Icon type="question-circle" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  },
-                  {
-                    max: formRule.input.max,
-                    message: formRule.input.message
-                  }
-                ]
-              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} onPressEnter={this.handleSubmit} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'number') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.tooltip ?
-              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
-                <Icon type="question-circle" />
-                {item.label}
-              </Tooltip> : item.label
-            }>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.input'] + item.label + '!'
-                  }
-                ]
-              })(<InputNumber min={item.min} max={item.max} precision={item.decimal} />)}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'select') { // 涓嬫媺鎼滅储
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || '',
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Select
-                  showSearch
-                  disabled={!!item.readonly}
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                  onChange={(value) => {this.typeChange(item.key, value)}}
-                  getPopupContainer={() => document.getElementById('chartwinter')}
-                >
-                  {item.options.map((option, index) =>
-                    <Select.Option id={`${index}`} title={option.text} key={`${index}`} value={option.value}>
-                      {option.text}
-                    </Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'radio') {
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal,
-                rules: [
-                  {
-                    required: !!item.required,
-                    message: this.props.dict['form.required.select'] + item.label + '!'
-                  }
-                ]
-              })(
-                <Radio.Group>
-                  {
-                    item.options.map(option => {
-                      return (
-                        <Radio key={option.value} value={option.value}>{option.text}</Radio>
-                      )
-                    })
-                  }
-                </Radio.Group>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      } else if (item.type === 'multiselect') { // 澶氶��
-        fields.push(
-          <Col span={12} key={index}>
-            <Form.Item label={item.label}>
-              {getFieldDecorator(item.key, {
-                initialValue: item.initVal || []
-              })(
-                <Select
-                  showSearch
-                  mode="multiple"
-                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
-                >
-                  {item.options.map((option, i) =>
-                    <Select.Option id={i} key={i} value={option.value}>{option.text}</Select.Option>
-                  )}
-                </Select>
-              )}
-            </Form.Item>
-          </Col>
-        )
-      }
-    })
-    return fields
-  }
-
-  handleConfirm = () => {
-    const { selectlegend } = this.state
-    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
-    return new Promise((resolve, reject) => {
-      this.props.form.validateFieldsAndScroll((err, values) => {
-        if (!err) {
-          let result = {...this.props.card, ...values}
-          
-          let icons = {
-            table: 'table',
-            line: 'line-chart',
-            bar: 'bar-chart',
-            pie: 'pie-chart'
-          }
-
-          if (selectlegend && this.props.card.modelId !== selectlegend.uuid) {
-            result = {...result, ...selectlegend.options}
-          }
-
-          if (selectlegend) {
-            result.modelId = selectlegend.uuid
-          }
-
-          if (result.chartType !== 'pie' && result.Yaxis && typeof(result.Yaxis) === 'string') {
-            result.Yaxis = [result.Yaxis]
-          } else if (result.chartType === 'pie' && result.Yaxis && typeof(result.Yaxis) === 'object') {
-            result.Yaxis = result.Yaxis[0] || ''
-          }
-
-          result.icon = icons[result.chartType]
-
-          resolve(result)
-        } else {
-          reject(err)
-        }
-      })
-    })
-  }
-
-  render() {
-    const { legends, selectlegend } = this.state
-    const formItemLayout = {
-      labelCol: {
-        xs: { span: 24 },
-        sm: { span: 6 }
-      },
-      wrapperCol: {
-        xs: { span: 24 },
-        sm: { span: 18 }
-      }
-    }
-    return (
-      <Form {...formItemLayout} className="chart-edit-form" id="chartwinter">
-        <Row gutter={24}>{this.getFields()}</Row>
-        {legends ? <Row gutter={24} className="chart-model-image">
-          {legends.map(item => <Col span={6} key={item.uuid}>
-            <img onClick={() => this.changeSelectLegend(item)} src={item.url} className={selectlegend.uuid === item.uuid ? 'active' : ''} alt=""/>
-          </Col>)}
-        </Row> : null}
-      </Form>
-    )
-  }
-}
-
-export default Form.create()(ChartForm)
\ No newline at end of file
diff --git a/src/templates/zshare/chartform/index.scss b/src/templates/zshare/chartform/index.scss
deleted file mode 100644
index a1778ca..0000000
--- a/src/templates/zshare/chartform/index.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-.chart-edit-form {
-  min-height: 190px;
-  .ant-form-item {
-    .ant-input-number {
-      width: 100%;
-    }
-  }
-  .anticon-question-circle {
-    color: #c49f47;
-    position: relative;
-    left: -3px;
-  }
-  .chart-model-image {
-    img {
-      max-width: 100%;
-      cursor: pointer;
-      border: 1px solid #ebedf0;
-      transition: all .3s;
-    }
-    img.active {
-      background-color: rgba(135,59,244,.1);
-      border-color: #873bf4;
-    }
-  }
-}
diff --git a/src/templates/zshare/dragelform/card.jsx b/src/templates/zshare/dragelform/card.jsx
deleted file mode 100644
index 8e31f09..0000000
--- a/src/templates/zshare/dragelform/card.jsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import React from 'react'
-import { useDrag, useDrop } from 'react-dnd'
-import { Icon, Select, DatePicker, Input } from 'antd'
-import moment from 'moment'
-import ItemTypes from './itemtypes'
-import './index.scss'
-
-const { MonthPicker, WeekPicker, RangePicker } = DatePicker
-
-const Card = ({ id, type, card, moveCard, findCard, editCard, delCard, hasDrop }) => {
-  const originalIndex = findCard(id).index
-  const [{ isDragging }, drag] = useDrag({
-    item: { type: ItemTypes[type], id, originalIndex },
-    collect: monitor => ({
-      isDragging: monitor.isDragging(),
-    }),
-  })
-  const [, drop] = useDrop({
-    accept: ItemTypes[type],
-    canDrop: () => true,
-    drop: (item) => {
-      if (!item.hasOwnProperty('originalIndex')) {
-        hasDrop(card)
-      }
-    },
-    hover({ id: draggedId }) {
-      if (!draggedId) return
-      if (draggedId !== id) {
-        const { index: overIndex } = findCard(id)
-        moveCard(draggedId, overIndex)
-      }
-    },
-  })
-  const opacity = isDragging ? 0 : 1
-
-  const edit = () => {
-    editCard(id)
-  }
-  
-  const del = () => {
-    delCard(id)
-  }
-
-  let _defaultValue = '' // 涓嬫媺鎼滅储銆佹椂闂磋寖鍥寸被鍨嬶紝鍒濆鍊奸渶瑕侀澶勭悊
-
-  if (card.type === 'multiselect' || card.type === 'select' || card.type === 'link') {
-    if (card.initval) {
-      let _option = card.options.filter(option => option.Value === card.initval)[0]
-      if (_option) {
-        _defaultValue = _option.Text || ''
-      } else {
-        _defaultValue = ''
-      }
-    } else if (card.setAll === 'true') {
-      _defaultValue = '鍏ㄩ儴'
-    }
-  } else if (card.type === 'daterange') {
-    _defaultValue = [null, null]
-    if (card.initval) {
-      try {
-        let _initval = JSON.parse(card.initval)
-        _defaultValue = [moment().subtract(_initval[0], 'days'), moment().subtract(_initval[1], 'days')]
-      } catch {
-        _defaultValue = [null, null]
-      }
-    }
-  }
-
-  return (
-    <div className="page-card" style={{ opacity: opacity}}>
-      <div ref={node => drag(drop(node))}>
-        <div className="ant-row ant-form-item">
-          <div className="ant-col ant-form-item-label">
-            <label title={card.label}>{card.label}</label>
-          </div>
-          <div className="ant-col ant-form-item-control-wrapper">
-            {card.type === 'text' ?
-              <Input style={{marginTop: '4px'}} defaultValue={card.initval} /> : null
-            }
-            {(card.type === 'multiselect' || card.type === 'select' || card.type === 'link') ?
-              <Select defaultValue={_defaultValue}></Select> : null
-            }
-            {card.type === 'date' ?
-              <DatePicker defaultValue={card.initval ? moment().subtract(card.initval, 'days') : null} /> : null
-            }
-            {card.type === 'dateweek' ?
-              <WeekPicker defaultValue={card.initval ? moment().subtract(card.initval * 7, 'days') : null} /> : null
-            }
-            {card.type === 'datemonth' ?
-              <MonthPicker defaultValue={card.initval ? moment().subtract(card.initval, 'month') : null} /> : null
-            }
-            {card.type === 'daterange' ?
-              <RangePicker
-                className="data-range"
-                placeholder={['寮�濮嬫棩鏈�', '缁撴潫鏃ユ湡']}
-                renderExtraFooter={() => 'extra footer'}
-                defaultValue={_defaultValue}
-              /> : null
-            }
-            <div className="input-mask"></div>
-          </div>
-        </div>
-      </div>
-      <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} />
-      <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} />
-    </div>
-  )
-}
-export default Card
diff --git a/src/templates/zshare/dragelform/index.jsx b/src/templates/zshare/dragelform/index.jsx
deleted file mode 100644
index 88958aa..0000000
--- a/src/templates/zshare/dragelform/index.jsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import React, { useState } from 'react'
-import { useDrop } from 'react-dnd'
-import { is, fromJS } from 'immutable'
-import update from 'immutability-helper'
-import { Col, Icon } from 'antd'
-import Utils from '@/utils/utils.js'
-import Card from './card'
-import ItemTypes from './itemtypes'
-import './index.scss'
-
-const Container = ({list, type, placeholder, handleList, handleMenu, deleteMenu }) => {
-  let target = null
-  
-  const [cards, setCards] = useState(list)
-  const moveCard = (id, atIndex) => {
-    const { card, index } = findCard(id)
-    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
-    handleList(type, _cards)
-  }
-
-  if (!is(fromJS(cards), fromJS(list))) {
-    setCards(list)
-  }
-  
-  const findCard = id => {
-    const card = cards.filter(c => `${c.uuid}` === id)[0]
-    return {
-      card,
-      index: cards.indexOf(card),
-    }
-  }
-
-  const editCard = id => {
-    const { card } = findCard(id)
-    handleMenu(card)
-  }
-
-  const delCard = id => {
-    const { card } = findCard(id)
-    deleteMenu({card: card, type: type})
-  }
-
-  const hasDrop = (item) => {
-    target = item
-  }
-
-  const [, drop] = useDrop({
-    accept: ItemTypes[type],
-    drop(item) {
-      if (item.hasOwnProperty('originalIndex')) {
-        return
-      }
-
-      let newcard = {}
-      newcard.uuid = Utils.getuuid()
-      newcard.focus = true
-      
-      let _match = 'like'
-      if (item.subType === 'select' || item.subType === 'link') {
-        _match = '='
-      } else if (item.subType === 'date' || item.subType === 'datemonth') {
-        _match = '>='
-      } else if (item.subType === 'dateweek' || item.subType === 'daterange') {
-        _match = 'between'
-      }
-      
-      newcard.label = 'label'
-      newcard.initval = ''
-      newcard.type = item.subType
-      newcard.resourceType = '0'
-      newcard.options = []
-      newcard.setAll = 'false'
-      newcard.orderType = 'asc'
-      newcard.match = _match
-      newcard.display = 'dropdown'
-      
-      let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
-      if (target) {
-        targetId = target.uuid
-      }
-
-      const { index: overIndex } = findCard(`${targetId}`)
-      let targetIndex = overIndex
-
-      targetIndex++
-
-      const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
-
-      handleList(type, _cards, newcard)
-      target = null
-    }
-  })
-
-  return (
-    <div ref={drop} className="ant-row">
-      {cards.map(card => (
-        <Col key={card.uuid} span={6}>
-          <Card
-            id={`${card.uuid}`}
-            type={type}
-            card={card}
-            moveCard={moveCard}
-            editCard={editCard}
-            delCard={delCard}
-            findCard={findCard}
-            hasDrop={hasDrop}
-          />
-        </Col>
-      ))}
-      {cards.length === 0 &&
-        <div className="common-drawarea-placeholder">
-          {placeholder}
-        </div>
-      }
-    </div>
-  )
-}
-export default Container
diff --git a/src/templates/zshare/dragelform/index.scss b/src/templates/zshare/dragelform/index.scss
deleted file mode 100644
index 38776f9..0000000
--- a/src/templates/zshare/dragelform/index.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-.common-source-item {
-  display: block;
-  box-shadow: 0px 0px 2px #bcbcbc;
-  padding: 0.4rem 0.7rem;
-  background-color: white;
-  margin: 0px 0px 10px;
-  cursor: move;
-  border-radius: 4px;
-}
-.common-drawarea-placeholder {
-  width: 100%;
-  line-height: 65px;
-  text-align: center;
-  color: #bcbcbc;
-}
\ No newline at end of file
diff --git a/src/templates/zshare/dragelform/itemtypes.js b/src/templates/zshare/dragelform/itemtypes.js
deleted file mode 100644
index 9ea1f2c..0000000
--- a/src/templates/zshare/dragelform/itemtypes.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
-  CARD: 'card',
-  form: 'form',
-  search: 'search',
-  action: 'action',
-  columns: 'columns',
-  tab: 'tab'
-}
diff --git a/src/templates/zshare/dragelform/source.jsx b/src/templates/zshare/dragelform/source.jsx
deleted file mode 100644
index ab22158..0000000
--- a/src/templates/zshare/dragelform/source.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react'
-import { useDrag } from 'react-dnd'
-import './index.scss'
-
-const SourceElement = ({content}) => {
-  const [, drag] = useDrag({ item: content })
-  return (
-    <div ref={drag} className="common-source-item">
-      {content.label}
-    </div>
-  )
-}
-export default SourceElement
\ No newline at end of file
diff --git a/src/templates/zshare/formconfig.jsx b/src/templates/zshare/formconfig.jsx
index 3b79d42..a21d0bd 100644
--- a/src/templates/zshare/formconfig.jsx
+++ b/src/templates/zshare/formconfig.jsx
@@ -1703,14 +1703,14 @@
       type: 'number',
       key: 'min',
       label: '鏈�灏忓��',
-      initVal: card.min || '',
+      initVal: card.min || card.min === 0 ? card.min : '',
       required: false
     },
     {
       type: 'number',
       key: 'max',
       label: '鏈�澶у��',
-      initVal: card.max || '',
+      initVal: card.max || card.max === 0 ? card.max : '',
       required: false
     },
     {
@@ -1879,4 +1879,103 @@
       options: roleList
     }
   ]
+}
+
+/**
+ * @description 鑾峰彇瀛愯彍鍗曞熀鏈俊鎭〃鍗曢厤缃俊鎭�
+ * @param {object} card  // 鏍囩閰嶇疆淇℃伅
+ */
+export function getTabForm (card, supMenu, menus, equalTab, equalTabs, type) {
+  return [
+    {
+      type: 'text',
+      key: 'label',
+      label: Formdict['header.menu.tabName'],
+      initVal: card.label || '',
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'type',
+      label: Formdict['header.form.tabType'],
+      initVal: card.type || 'SubTable',
+      required: true,
+      options: [{
+        value: 'SubTable',
+        text: Formdict['header.menu.tab.subtable']
+      }]
+    },
+    {
+      type: 'select',
+      key: 'linkTab',
+      label: Formdict['header.form.linkTab'],
+      initVal: card.linkTab || '',
+      required: false,
+      options: []
+    },
+    {
+      type: 'select',
+      key: 'icon',
+      label: Formdict['header.menu.icon'],
+      initVal: card.icon || '',
+      required: false,
+      options: [{
+        value: '',
+        text: Formdict['header.form.empty']
+      }, {
+        value: 'table',
+        text: 'table'
+      }, {
+        value: 'bar-chart',
+        text: 'bar-chart'
+      }, {
+        value: 'pie-chart',
+        text: 'pie-chart'
+      }, {
+        value: 'line-chart',
+        text: 'line-chart'
+      }]
+    },
+    {
+      type: 'select',
+      key: 'supMenu',
+      label: Formdict['header.form.supTab'],
+      initVal: supMenu,
+      required: false,
+      options: menus
+    },
+    {
+      type: 'mutilselect',
+      key: 'equalTab',
+      label: Formdict['header.form.equalTab'],
+      tooltip: '濡傛灉瀛愭爣绛句腑鍚湁鍒锋柊鍚岀骇鏍囩鐨勬寜閽紝鍦ㄦ澶勬坊鍔犻渶瑕佸埛鏂扮殑鏍囩銆�',
+      initVal: equalTab,
+      required: false,
+      options: equalTabs
+    },
+    {
+      type: 'text',
+      key: 'foreignKey',
+      label: '澶栭敭',
+      tooltip: '澶栭敭鏃ㄥ湪鏍囩椤典腑鎵ц榛樿鍑芥暟锛堟坊鍔狅級鏃讹紝鏇挎崲BID瀛楁',
+      initVal: card.foreignKey || '',
+      required: false
+    },
+    {
+      type: 'radio',
+      key: 'searchPass',
+      label: '涓昏〃鎼滅储',
+      initVal: card.searchPass || 'false',
+      tooltip: '浣跨敤涓昏〃鎼滅储鏉′欢鏃讹紝涓昏〃鐨勬悳绱㈡潯浠朵細浼犲叆瀛愯〃涓��',
+      required: false,
+      forbid: type !== 'main',
+      options: [{
+        value: 'true',
+        text: '浣跨敤'
+      }, {
+        value: 'false',
+        text: '涓嶄娇鐢�'
+      }]
+    }
+  ]
 }
\ No newline at end of file
diff --git a/src/templates/zshare/searcheditable/index.jsx b/src/templates/zshare/searcheditable/index.jsx
deleted file mode 100644
index 027ab1e..0000000
--- a/src/templates/zshare/searcheditable/index.jsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import React, {Component} from 'react'
-import { is, fromJS } from 'immutable'
-import { Table, Input, Button, Popconfirm, Form, Icon } from 'antd'
-import Utils from '@/utils/utils.js'
-import './index.scss'
-
-const EditableContext = React.createContext()
-
-const EditableRow = ({ form, index, ...props }) => (
-  <EditableContext.Provider value={form}>
-    <tr {...props} />
-  </EditableContext.Provider>
-)
-
-const EditableFormRow = Form.create()(EditableRow)
-
-class EditableCell extends Component {
-  state = {
-    editing: false
-  }
-
-  toggleEdit = () => {
-    const editing = !this.state.editing
-    this.setState({ editing }, () => {
-      if (editing && this.input && this.input.select) {
-        this.input.select()
-      } else if (editing && this.input && this.input.focus) {
-        this.input.focus()
-      }
-    })
-  }
-
-  save = e => {
-    const { record, handleSave } = this.props
-    this.form.validateFields((error, values) => {
-      handleSave({ ...record, ...values })
-      if (error && error[e.currentTarget.id]) {
-        return
-      }
-      this.toggleEdit()
-    })
-  }
-
-  renderCell = form => {
-    this.form = form
-    const { children, dataIndex, record } = this.props
-    const { editing } = this.state
-    return editing ? (
-      <Form.Item style={{ margin: 0 }}>
-        {form.getFieldDecorator(dataIndex, {
-          rules: [
-            {
-              required: true,
-              message: 'NOT NULL.',
-            },
-          ],
-          initialValue: record[dataIndex]
-        })(<Input ref={node => (this.input = node)} autoComplete="off" onPressEnter={this.save} onBlur={this.save} />)}
-      </Form.Item>
-    ) : (
-      <div
-        className="editable-cell-value-wrap"
-        onClick={this.toggleEdit}
-      >
-        {children}
-      </div>
-    )
-  }
-
-  render() {
-    const {
-      editable,
-      dataIndex,
-      title,
-      record,
-      index,
-      handleSave,
-      children,
-      ...restProps
-    } = this.props
-    return (
-      <td {...restProps}>
-        {editable ? (
-          <EditableContext.Consumer style={{padding: 0}}>{this.renderCell}</EditableContext.Consumer>
-        ) : (
-          children
-        )}
-      </td>
-    )
-  }
-}
-
-class EditTable extends Component {
-  constructor(props) {
-    super(props)
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: props.type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (props.type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.state = {
-      columns: columns,
-      dataSource: props.data,
-      count: props.data.length,
-      type: props.type
-    }
-  }
-
-  handleDelete = key => {
-    const dataSource = [...this.state.dataSource]
-    this.setState({ dataSource: dataSource.filter(item => item.key !== key) })
-  }
-
-  handleAdd = () => {
-    const { type, count, dataSource } = this.state
-    const newData = {
-      key: Utils.getuuid(),
-      Value: `${count}`,
-      Text: `${count}`
-    }
-    if (type === 'link') {
-      newData.ParentID = `${count}`
-    }
-    this.setState({
-      dataSource: [...dataSource, newData],
-      count: count + 1
-    })
-  }
-
-  handleSave = row => {
-    const newData = [...this.state.dataSource]
-    const index = newData.findIndex(item => row.key === item.key)
-    const item = newData[index]
-    newData.splice(index, 1, {
-      ...item,
-      ...row
-    })
-    this.setState({ dataSource: newData })
-  }
-
-  resetColumn = (type) => {
-    let columns = [
-      {
-        title: 'Value',
-        dataIndex: 'Value',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: 'Text',
-        dataIndex: 'Text',
-        width: type === 'link' ? '27%' : '40%',
-        editable: true
-      },
-      {
-        title: '鎿嶄綔',
-        align: 'center',
-        dataIndex: 'operation',
-        render: (text, record) =>
-          this.state.dataSource.length >= 1 ? (
-            <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
-              <span style={{color: '#1890ff', cursor: 'pointer'}}><Icon type="delete" /></span>
-            </Popconfirm>
-          ) : null,
-      }
-    ]
-
-    if (type === 'link') {
-      columns.unshift({
-        title: 'ParentID',
-        dataIndex: 'ParentID',
-        width: '27%',
-        editable: true
-      })
-    }
-
-    this.setState({
-      columns: columns,
-      type: type
-    })
-  }
-
-  UNSAFE_componentWillReceiveProps (nextProps) {
-    if (this.props.type !== nextProps.type) {
-      this.resetColumn(nextProps.type)
-    } else if (!is(fromJS(this.props.data), fromJS(nextProps.data))) {
-      this.setState({
-        dataSource: nextProps.data,
-        count: nextProps.data.length
-      })
-    }
-  }
-
-  render() {
-    const { dataSource } = this.state
-    const components = {
-      body: {
-        row: EditableFormRow,
-        cell: EditableCell
-      }
-    }
-    const columns = this.state.columns.map(col => {
-      if (!col.editable) {
-        return col
-      }
-      return {
-        ...col,
-        onCell: record => ({
-          record,
-          editable: col.editable,
-          dataIndex: col.dataIndex,
-          title: col.title,
-          handleSave: this.handleSave,
-        })
-      }
-    })
-    return (
-      <div className="common-modal-edit-table">
-        <Button onClick={this.handleAdd} type="primary" className="add-row">
-          娣诲姞
-        </Button>
-        <Table
-          components={components}
-          rowClassName={() => 'editable-row'}
-          bordered
-          dataSource={dataSource}
-          columns={columns}
-          pagination={false}
-        />
-      </div>
-    )
-  }
-}
-
-export default EditTable
\ No newline at end of file
diff --git a/src/templates/zshare/searcheditable/index.scss b/src/templates/zshare/searcheditable/index.scss
deleted file mode 100644
index f8f0942..0000000
--- a/src/templates/zshare/searcheditable/index.scss
+++ /dev/null
@@ -1,36 +0,0 @@
-.common-modal-edit-table {
-  .add-row {
-    position: absolute;
-    z-index: 1;
-    right: 12px;
-    top: -40px;
-  }
-  .ant-table-thead > tr > th {
-    padding: 10px 16px;
-  }
-  .ant-table-tbody > tr > td {
-    padding: 0px 16px;
-  }
-  .editable-cell-value-wrap {
-    cursor: pointer;
-    height: 40px;
-    width: 100px;
-    display: table-cell;
-    vertical-align: middle;
-    word-wrap: break-word;
-    word-break: break-word;
-    .ant-input {
-      height: 30px;
-      padding: 0 11px;
-    }
-  }
-  .ant-form-item-control-wrapper {
-    width: 100%;
-  }
-  .ant-table-placeholder {
-    padding: 5px 16px;
-    .ant-empty-normal {
-      margin: 0;
-    }
-  }
-}
diff --git a/src/templates/zshare/tabdragelement/index.scss b/src/templates/zshare/tabdragelement/index.scss
deleted file mode 100644
index 56fbd3b..0000000
--- a/src/templates/zshare/tabdragelement/index.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-.common-source-item {
-  display: block;
-  box-shadow: 0px 0px 2px #bcbcbc;
-  padding: 0.4rem 0.7rem;
-  background-color: white;
-  margin: 0px 0px 10px;
-  cursor: move;
-  border-radius: 4px;
-}
-.maintable-tab-list {
-  .ant-tabs-content {
-    text-align: center;
-    color: #bcbcbc;
-  }
-  .commontab-drawarea-placeholder {
-    position: absolute;
-    top: 25px;
-    left: calc(50% - 50px);
-    color: #bcbcbc;
-  }
-}
\ No newline at end of file
diff --git a/src/templates/zshare/viewdragelement/card.jsx b/src/templates/zshare/viewdragelement/card.jsx
deleted file mode 100644
index b44ab02..0000000
--- a/src/templates/zshare/viewdragelement/card.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react'
-import { useDrag, useDrop } from 'react-dnd'
-import { Icon } from 'antd'
-import './index.scss'
-
-const Card = ({ id, card, moveCard, findCard, editCard, delCard }) => {
-  const originalIndex = findCard(id).index
-
-  const [{ isDragging }, drag] = useDrag({
-    item: { type: 'chart', id, originalIndex },
-    collect: monitor => ({
-      isDragging: monitor.isDragging(),
-    }),
-  })
-
-  const opacity = isDragging ? 0 : 1
-
-  const edit = () => {
-    editCard(id)
-  }
-  
-  const del = () => {
-    delCard(id)
-  }
-
-  const [, drop] = useDrop({
-    accept: 'chart',
-    canDrop: () => true,
-    hover({ id: draggedId }) {
-      if (!draggedId) return
-      if (draggedId !== id) {
-        const { index: overIndex } = findCard(id)
-        moveCard(draggedId, overIndex)
-      }
-    }
-  })
-
-  return (
-    <div className="chart-tab" style={{ opacity: opacity}}>
-      <div ref={node => drag(drop(node))}>
-        <Icon type={card.icon} />
-      </div>
-      <Icon className="edit" title="缂栬緫" type="edit" onClick={edit} />
-      {card.chartType !== 'table' ? <Icon className="edit close" title="鍒犻櫎" type="close" onClick={del} /> : null}
-    </div>
-  )
-}
-export default Card
diff --git a/src/templates/zshare/viewdragelement/index.jsx b/src/templates/zshare/viewdragelement/index.jsx
deleted file mode 100644
index c09197a..0000000
--- a/src/templates/zshare/viewdragelement/index.jsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React, { useState } from 'react'
-import { useDrop } from 'react-dnd'
-import { is, fromJS } from 'immutable'
-import update from 'immutability-helper'
-import { Tabs } from 'antd'
-import Card from './card'
-import './index.scss'
-
-const { TabPane } = Tabs
-
-const Container = ({activeKey, list, handleList, handleMenu, deleteMenu, changetabview }) => {
-  const [cards, setCards] = useState(list)
-  const moveCard = (id, atIndex) => {
-    const { card, index } = findCard(id)
-    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
-
-    handleList(_cards)
-  }
-
-  if (!is(fromJS(cards), fromJS(list))) {
-    setCards(list)
-  }
-  
-  const findCard = id => {
-    const card = cards.filter(c => `${c.uuid}` === id)[0]
-    return {
-      card,
-      index: cards.indexOf(card),
-    }
-  }
-
-  const editCard = id => {
-    const { card } = findCard(id)
-    handleMenu(card)
-  }
-
-  const delCard = id => {
-    const { card } = findCard(id)
-    deleteMenu(card)
-  }
-
-  const changetab = id => {
-    if (activeKey === 'all') return
-    
-    changetabview(id)
-  }
-
-  const [, drop] = useDrop({
-    accept: 'chart'
-  })
-
-  return (
-    <div ref={drop} className="ant-row chart-edit-tab-box">
-      <Tabs activeKey={activeKey} onChange={changetab}>
-        {cards.map(card => (
-          <TabPane tab={
-            <div key={card.uuid}>
-              <Card
-                key={card.uuid}
-                id={card.uuid}
-                card={card}
-                moveCard={moveCard}
-                editCard={editCard}
-                delCard={delCard}
-                findCard={findCard}
-              />
-            </div>
-          } key={card.uuid}></TabPane>
-        ))}
-      </Tabs>
-      {/* {cards.map(card => (
-        <Card
-          id={card.uuid}
-          key={card.uuid}
-          card={card}
-          moveCard={moveCard}
-          editCard={editCard}
-          delCard={delCard}
-          findCard={findCard}
-        />
-      ))} */}
-    </div>
-  )
-}
-export default Container
diff --git a/src/templates/zshare/viewdragelement/index.scss b/src/templates/zshare/viewdragelement/index.scss
deleted file mode 100644
index 91c831e..0000000
--- a/src/templates/zshare/viewdragelement/index.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-.chart-edit-tab-box {
-  padding-right: 100px;
-  display: inline-block;
-
-  .ant-tabs-bar {
-    border: 0;
-  }
-  .ant-tabs-tab {
-    margin: 0px;
-    padding: 0px;
-  }
-  .ant-tabs-ink-bar {
-    display: none!important;
-  }
-  .chart-tab {
-    position: relative;
-    width: 40px;
-    padding-top: 15px;
-    text-align: center;
-    display: inline-block;
-    
-    .edit {
-      position: absolute;
-      left: 0;
-      top: 0px;
-      color: #1890ff;
-      cursor: pointer;
-      display: none;
-    }
-    .edit.close {
-      left: 20px;
-      color: #ff4d4f;
-    }
-  }
-
-  .chart-tab:hover {
-    .edit {
-      display: inline-block;
-    }
-  }
-}
\ No newline at end of file

--
Gitblit v1.8.0