From 89fb1308d92e10a27cf8f91f4dd766eb38976e12 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 26 十一月 2020 21:56:42 +0800
Subject: [PATCH] 2020-11-26

---
 src/tabviews/custom/components/chart/antv-bar-line/index.jsx                          |   66 +
 src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx                        |   17 
 src/templates/subtableconfig/source.jsx                                               |    9 
 src/menu/components/table/normal-table/columncomponent/index.jsx                      |  509 ++++++++++
 src/menu/components/table/normal-table/columncomponent/columnform/index.scss          |   19 
 src/menu/actioncomponent/actionform/index.jsx                                         |    9 
 src/menu/actioncomponent/dragaction/index.jsx                                         |   36 
 src/menu/actioncomponent/index.jsx                                                    |   18 
 src/menu/components/table/normal-table/columncomponent/colspanform/index.jsx          |  211 ++++
 src/menu/components/table/normal-table/columncomponent/gridbtnform/index.scss         |    8 
 src/templates/sharecomponent/searchcomponent/index.jsx                                |    4 
 src/views/menudesign/menuform/index.jsx                                               |    8 
 src/locales/zh-CN/model.js                                                            |    1 
 src/menu/components/table/normal-table/columncomponent/markcolumn/index.jsx           |  242 ++++
 src/templates/formtabconfig/dragelement/index.jsx                                     |    1 
 src/menu/components/chart/antv-bar/index.jsx                                          |    2 
 src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.jsx  |  384 +++++++
 src/menu/components/table/normal-table/index.scss                                     |   62 
 src/menu/components/card/table-card/cardcomponent/index.jsx                           |    1 
 src/menu/components/table/normal-table/columncomponent/colspanform/index.scss         |   13 
 src/menu/components/table/normal-table/columncomponent/columnform/index.jsx           |  336 ++++++
 src/locales/en-US/model.js                                                            |    1 
 src/views/mobdesign/index.jsx                                                         |   71 -
 src/views/menudesign/index.jsx                                                        |   10 
 src/utils/utils.js                                                                    |   18 
 src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx                        |   23 
 src/menu/components/table/normal-table/columncomponent/dragcolumn/card.jsx            |   62 +
 src/menu/components/table/normal-table/cardcomponent/index.jsx                        |    1 
 src/tabviews/custom/components/share/tabtransfer/index.jsx                            |   10 
 src/menu/components/card/cardcellcomponent/index.jsx                                  |   31 
 src/templates/comtableconfig/source.jsx                                               |   11 
 src/menu/components/chart/antv-pie/chartcompile/index.jsx                             |    6 
 src/tabviews/custom/components/chart/antv-pie/index.jsx                               |    1 
 src/menu/components/card/cardcomponent/index.jsx                                      |    1 
 src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx                     |   14 
 src/menu/components/chart/antv-pie/index.jsx                                          |    2 
 src/menu/components/table/normal-table/columncomponent/dragcolumn/index.jsx           |  174 +++
 src/templates/sharecomponent/actioncomponent/index.jsx                                |    2 
 src/tabviews/custom/index.jsx                                                         |   11 
 src/templates/sharecomponent/actioncomponent/dragaction/index.jsx                     |    1 
 src/menu/components/table/normal-table/columncomponent/index.scss                     |   99 ++
 src/menu/components/table/normal-table/columncomponent/gridbtnform/index.jsx          |  218 ++++
 src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.scss |    7 
 src/menu/components/table/normal-table/index.jsx                                      |   96 +
 src/menu/components/table/normal-table/columncomponent/markcolumn/index.scss          |   67 +
 src/menu/components/table/normal-table/columncomponent/dragcolumn/index.scss          |    6 
 46 files changed, 2,628 insertions(+), 271 deletions(-)

diff --git a/src/locales/en-US/model.js b/src/locales/en-US/model.js
index d769ab7..7e60392 100644
--- a/src/locales/en-US/model.js
+++ b/src/locales/en-US/model.js
@@ -198,7 +198,6 @@
   'header.form.topPicBottomText': '涓婂浘涓嬫枃',
   'header.form.leftPicRightText': '宸﹀浘鍙虫枃',
   'model.form.selectItem.error': '涓嬫媺閫夐」璁剧疆閿欒锛�',
-  'header.form.request.method': '璇锋眰鏂瑰紡',
   'header.form.readonly': '鍙',
   'header.form.queryType': '鏌ヨ绫诲瀷',
   'header.form.query': '鏌ヨ',
diff --git a/src/locales/zh-CN/model.js b/src/locales/zh-CN/model.js
index bd33160..b306629 100644
--- a/src/locales/zh-CN/model.js
+++ b/src/locales/zh-CN/model.js
@@ -198,7 +198,6 @@
   'header.form.topPicBottomText': '涓婂浘涓嬫枃',
   'header.form.leftPicRightText': '宸﹀浘鍙虫枃',
   'model.form.selectItem.error': '涓嬫媺閫夐」璁剧疆閿欒锛�',
-  'header.form.request.method': '璇锋眰鏂瑰紡',
   'header.form.readonly': '鍙',
   'header.form.queryType': '鏌ヨ绫诲瀷',
   'header.form.query': '鏌ヨ',
diff --git a/src/menu/actioncomponent/actionform/index.jsx b/src/menu/actioncomponent/actionform/index.jsx
index 3c00ca0..99a6a01 100644
--- a/src/menu/actioncomponent/actionform/index.jsx
+++ b/src/menu/actioncomponent/actionform/index.jsx
@@ -48,9 +48,6 @@
       text: this.props.dict['header.form.requiredOnce']
     }],
     insertUpdateOptions: [{
-      value: '',
-      text: this.props.dict['model.empty']
-    }, {
       value: 'insert',
       text: this.props.dict['header.form.action.insert']
     }, {
@@ -153,7 +150,7 @@
           _options.push('execMode', 'intertype', 'innerFunc', 'Ot', 'execSuccess', 'execError')
         }
       }
-    } else if (_opentype === 'popview' && _opentype === 'tab') {
+    } else if (_opentype !== 'popview' && _opentype !== 'tab') {
       if (_intertype === 'outer') {
         _options.push('innerFunc', 'sysInterface', 'interface', 'outerFunc', 'callbackFunc')
       } else if (_intertype === 'inner') {
@@ -598,9 +595,7 @@
               values.OpenType = values.execMode
             }
           } else if (['pop', 'prompt', 'exec'].includes(values.OpenType) && values.verify) {
-            if (values.Ot === 'requiredOnce' && ['notRequired', 'requiredSgl', 'required'].includes(this.props.card.Ot)) {
-              values.verify.uniques = []
-            } else if (this.props.card.Ot === 'requiredOnce' && ['notRequired', 'requiredSgl', 'required'].includes(values.Ot)) {
+            if ((values.Ot === 'requiredOnce' || this.props.card.Ot === 'requiredOnce') && this.props.card.Ot !== values.Ot) {
               values.verify.uniques = []
             }
           }
diff --git a/src/menu/actioncomponent/dragaction/index.jsx b/src/menu/actioncomponent/dragaction/index.jsx
index af88544..8024806 100644
--- a/src/menu/actioncomponent/dragaction/index.jsx
+++ b/src/menu/actioncomponent/dragaction/index.jsx
@@ -2,13 +2,12 @@
 import { useDrop } from 'react-dnd'
 import { is, fromJS } from 'immutable'
 import update from 'immutability-helper'
-import { Icon } from 'antd'
 
 import Utils from '@/utils/utils.js'
 import Card from './card'
 import './index.scss'
 
-const Container = ({plus, list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => {
+const Container = ({list, handleList, handleMenu, deleteMenu, profileMenu, doubleClickCard }) => {
   const [cards, setCards] = useState(list)
   const moveCard = (id, atIndex) => {
     const { card, index } = findCard(id)
@@ -90,38 +89,6 @@
     drop() {}
   })
 
-  const addaction = () => {
-    let newcard = {}
-    newcard.uuid = Utils.getuuid()
-    newcard.focus = true
-    
-    newcard.label = 'button'
-    newcard.sqlType = ''
-    newcard.Ot = 'requiredSgl'
-    newcard.OpenType = 'prompt'
-    newcard.icon = ''
-    newcard.class = 'primary'
-    newcard.intertype = 'system'
-    newcard.method = 'POST'
-    newcard.execSuccess = 'grid'
-    newcard.execError = 'never'
-    newcard.popClose = 'never'
-    newcard.errorTime = 10
-    newcard.verify = null
-    newcard.show = 'icon'
-    
-    let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
-
-    const { index: overIndex } = findCard(`${targetId}`)
-    let targetIndex = overIndex
-
-    targetIndex++
-
-    const _cards = update(cards, { $splice: [[targetIndex, 0, newcard]] })
-
-    handleList(_cards, newcard)
-  }
-
   return (
     <div ref={drop} className="ant-row">
       {cards.map(card => (
@@ -138,7 +105,6 @@
           doubleClickCard={doubleClickBtn}
         />
       ))}
-      {plus !== 'false' ? <Icon type="plus" title="娣诲姞鎸夐挳" onClick={addaction}/> : null}
     </div>
   )
 }
diff --git a/src/menu/actioncomponent/index.jsx b/src/menu/actioncomponent/index.jsx
index 56c3f6d..aab64b2 100644
--- a/src/menu/actioncomponent/index.jsx
+++ b/src/menu/actioncomponent/index.jsx
@@ -25,7 +25,6 @@
 class ActionComponent extends Component {
   static propTpyes = {
     type: PropTypes.string,          // 鑿滃崟绫诲瀷锛屼富琛ㄦ垨瀛愯〃
-    plus: PropTypes.any,             // 鏄惁瀛樺湪娣诲姞鎸夐挳锛屽�间负false鏃堕殣钘�
     config: PropTypes.object,        // 鑿滃崟閰嶇疆淇℃伅
     setSubConfig: PropTypes.func,    // 璁剧疆瀛愰厤缃俊鎭�
     updateaction: PropTypes.func     // 鑿滃崟閰嶇疆鏇存柊
@@ -177,7 +176,17 @@
       <p>{this.state.dict['model.tooltip.func.outface']}</p>
     </div>
 
-    let menulist = menu.fstMenuList ? menu.fstMenuList : []
+    let menulist = sessionStorage.getItem('fstMenuList')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
+    
     let modules = this.getModules(menu.components, config.uuid)
 
     this.setState({
@@ -409,13 +418,12 @@
   }
 
   render() {
-    const { config, plus } = this.props
+    const { config } = this.props
     const { actionlist, visible, card, dict, profVisible } = this.state
 
     return (
-      <div className="model-menu-action-list">
+      <div className={'model-menu-action-list length' + actionlist.length}>
         <DragElement
-          plus={plus}
           list={actionlist}
           handleList={this.handleList}
           handleMenu={this.handleAction}
diff --git a/src/menu/components/card/cardcellcomponent/index.jsx b/src/menu/components/card/cardcellcomponent/index.jsx
index 8faa4f7..9d8b224 100644
--- a/src/menu/components/card/cardcellcomponent/index.jsx
+++ b/src/menu/components/card/cardcellcomponent/index.jsx
@@ -261,28 +261,15 @@
       <p>{this.state.dict['model.tooltip.func.outface']}</p>
     </div>
 
-    let menulist = []
-    if (menu.fstMenuList) {
-      let trees = fromJS(menu.fstMenuList).toJS()
-
-      menulist = trees.map(fst => {
-        fst.value = fst.MenuID
-        fst.label = fst.MenuName
-        fst.isLeaf = false
-        fst.children = fst.children.map(snd => {
-          snd.value = snd.MenuID
-          snd.label = snd.MenuName
-
-          snd.children = snd.children.map(thd => {
-            thd.value = thd.MenuID
-            thd.label = thd.MenuName
-            thd.disabled = thd.MenuID === menu.MenuID
-            return thd
-          })
-          return snd
-        })
-        return fst
-      })
+    let menulist = sessionStorage.getItem('fstMenuList')
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch {
+        menulist = []
+      }
+    } else {
+      menulist = []
     }
 
     let modules = this.getModules(menu.components, cards.uuid)
diff --git a/src/menu/components/card/cardcomponent/index.jsx b/src/menu/components/card/cardcomponent/index.jsx
index ecffdf5..ab07f66 100644
--- a/src/menu/components/card/cardcomponent/index.jsx
+++ b/src/menu/components/card/cardcomponent/index.jsx
@@ -158,7 +158,6 @@
     newcard.icon = ''
     newcard.class = 'primary'
     newcard.intertype = 'system'
-    newcard.method = 'POST'
     newcard.execSuccess = 'grid'
     newcard.execError = 'never'
     newcard.popClose = 'never'
diff --git a/src/menu/components/card/table-card/cardcomponent/index.jsx b/src/menu/components/card/table-card/cardcomponent/index.jsx
index 3d0f004..7cf24f4 100644
--- a/src/menu/components/card/table-card/cardcomponent/index.jsx
+++ b/src/menu/components/card/table-card/cardcomponent/index.jsx
@@ -123,7 +123,6 @@
     newcard.icon = ''
     newcard.class = 'primary'
     newcard.intertype = 'system'
-    newcard.method = 'POST'
     newcard.execSuccess = 'grid'
     newcard.execError = 'never'
     newcard.popClose = 'never'
diff --git a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
index 71194ee..3b709ed 100644
--- a/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-bar/chartcompile/formconfig.jsx
@@ -6,9 +6,20 @@
 /**
  * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
  * @param {object} card       // 鍥捐〃瀵硅薄
- * @param {Array}  columns    // 鏄剧ず鍒�
+ * @param {Array}  MenuType   // 鑿滃崟绫诲瀷
  */
 export function getBaseForm (card, MenuType) {
+  let menulist = sessionStorage.getItem('fstMenuList')
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
   let roleList = sessionStorage.getItem('sysRoles')
   if (roleList) {
     try {
@@ -66,6 +77,16 @@
       required: false,
       forbid: MenuType === 'billPrint',
       options: roleList
+    },
+    {
+      type: 'cascader',
+      key: 'linkmenu',
+      label: '鍏宠仈鑿滃崟',
+      initVal: card.linkmenu || [],
+      tooltip: '鍦ㄤ娇鐢ㄦ煴褰㈠浘涓旀湭鍚敤鑷畾涔夎缃椂鏈夋晥銆�',
+      required: false,
+      forbid: MenuType === 'billPrint',
+      options: menulist
     }
   ]
 }
diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index a2efa3a..57f2fe4 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -791,7 +791,6 @@
     newcard.sysInterface = card.setting.sysInterface || ''
     newcard.outerFunc = card.setting.outerFunc || ''
     newcard.interface = card.setting.interface || ''
-    newcard.method = 'POST'
     newcard.execSuccess = 'grid'
     newcard.execError = 'never'
     newcard.popClose = 'never'
@@ -866,7 +865,6 @@
         </Popover>
         {menu && menu.MenuType !== 'billPrint' ? <ActionComponent
           type="chart"
-          plus="false"
           config={card}
           updateaction={this.updateComponent}
         /> : null}
diff --git a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
index c9d6fc6..8a248f0 100644
--- a/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
+++ b/src/menu/components/chart/antv-pie/chartcompile/formconfig.jsx
@@ -6,9 +6,20 @@
 /**
  * @description 鑾峰彇鍥捐〃瑙嗗浘閰嶇疆琛ㄥ崟
  * @param {object} card       // 鍥捐〃瀵硅薄
- * @param {Array}  columns    // 鏄剧ず鍒�
+ * @param {Array}  MenuType   // 鑿滃崟绫诲瀷
  */
-export function getBaseForm (card, MenuType, fstMenuList = []) {
+export function getBaseForm (card, MenuType) {
+  let menulist = sessionStorage.getItem('fstMenuList')
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
   let roleList = sessionStorage.getItem('sysRoles')
   if (roleList) {
     try {
@@ -75,7 +86,7 @@
       tooltip: '鍙屽嚮楗煎浘锛屼細鎵撳紑鍏宠仈鐨勮彍鍗曘��',
       required: false,
       forbid: MenuType === 'billPrint',
-      options: fstMenuList
+      options: menulist
     }
   ]
 }
diff --git a/src/menu/components/chart/antv-pie/chartcompile/index.jsx b/src/menu/components/chart/antv-pie/chartcompile/index.jsx
index 7678833..ce879c3 100644
--- a/src/menu/components/chart/antv-pie/chartcompile/index.jsx
+++ b/src/menu/components/chart/antv-pie/chartcompile/index.jsx
@@ -16,7 +16,7 @@
 
 class LineChartDrawerForm extends Component {
   static propTpyes = {
-    menu: PropTypes.any,
+    MenuType: PropTypes.any,
     dict: PropTypes.object,
     plot: PropTypes.object,
     config: PropTypes.object,
@@ -51,13 +51,13 @@
   }
 
   showDrawer = () => {
-    const { config, menu } = this.props
+    const { config, MenuType } = this.props
 
     this.setState({
       visible: true,
       view: 'normal',
       plot: fromJS(config.plot).toJS(),
-      baseFormlist: getBaseForm(config.plot, menu.MenuType, menu.fstMenuList),
+      baseFormlist: getBaseForm(config.plot, MenuType),
       formlist: getOptionForm(config.plot, config.columns)
     })
   }
diff --git a/src/menu/components/chart/antv-pie/index.jsx b/src/menu/components/chart/antv-pie/index.jsx
index 496f25d..e65d64a 100644
--- a/src/menu/components/chart/antv-pie/index.jsx
+++ b/src/menu/components/chart/antv-pie/index.jsx
@@ -426,7 +426,7 @@
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
             {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null}
-            <ChartCompileForm config={card} menu={menu} dict={this.state.dict} plotchange={this.updateComponent}/>
+            {menu ? <ChartCompileForm config={card} MenuType={menu.MenuType} dict={this.state.dict} plotchange={this.updateComponent}/> : null}
             <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
             <Icon className="close" title="delete" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
             <SettingComponent config={card} updateConfig={this.updateComponent}/>
diff --git a/src/menu/components/table/normal-table/cardcomponent/index.jsx b/src/menu/components/table/normal-table/cardcomponent/index.jsx
index 3d0f004..7cf24f4 100644
--- a/src/menu/components/table/normal-table/cardcomponent/index.jsx
+++ b/src/menu/components/table/normal-table/cardcomponent/index.jsx
@@ -123,7 +123,6 @@
     newcard.icon = ''
     newcard.class = 'primary'
     newcard.intertype = 'system'
-    newcard.method = 'POST'
     newcard.execSuccess = 'grid'
     newcard.execError = 'never'
     newcard.popClose = 'never'
diff --git a/src/menu/components/table/normal-table/columncomponent/colspanform/index.jsx b/src/menu/components/table/normal-table/columncomponent/colspanform/index.jsx
new file mode 100644
index 0000000..8474416
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/colspanform/index.jsx
@@ -0,0 +1,211 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, InputNumber, Select, Radio, Tooltip, Icon } from 'antd'
+import { formRule } from '@/utils/option.js'
+import TransferForm from '@/templates/zshare/transferform'
+import './index.scss'
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    columns: PropTypes.array,
+    card: PropTypes.any,
+    inputSubmit: PropTypes.any   // 鍥炶溅鎻愪氦浜嬩欢
+  }
+
+  componentDidMount () {
+    try {
+      let _form = document.getElementById('label')
+      if (_form && _form.select) {
+        _form.select()
+      }
+    } catch {
+      console.warn('琛ㄥ崟focus澶辫触锛�')
+    }
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          let targetKeys = this.refs['column-transfer'].state.targetKeys
+
+          delete values.type // 鍒犻櫎type锛屾澶勫�间负'鍚堝苟鍒�'鏂囧瓧
+
+          let subfield = []  // 鐢ㄤ簬鏌ョ湅鍚堝苟鍒楀瓧娈�
+          this.props.columns.forEach(col => {
+            if (col.field && targetKeys.includes(col.uuid)) {
+              subfield.push(col.field)
+            }
+          })
+          subfield = subfield.join(', ')
+
+          let _card = {...this.props.card, ...values, sublist: targetKeys, subfield: subfield}
+
+          delete _card.focus
+
+          resolve(_card)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  render() {
+    const { card } = this.props
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="commontable-cospan-column-form" id="columncolspan">
+        <Row gutter={24}>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['model.name']}>
+              {getFieldDecorator('label', {
+                initialValue: card.label,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + this.props.dict['model.name'] + '!'
+                  },
+                  {
+                    max: formRule.input.max,
+                    message: formRule.input.message
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" onPressEnter={this.handleSubmit} />)}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['model.form.type']}>
+              {getFieldDecorator('type', {
+                initialValue: this.props.dict['model.form.colspan'],
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + this.props.dict['model.form.type'] + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" disabled={true}/>)}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['model.form.align']}>
+              {getFieldDecorator('Align', {
+                initialValue: card.Align,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + this.props.dict['model.form.align'] + '!'
+                  }
+                ]
+              })(
+                <Select
+                  getPopupContainer={() => document.getElementById('columncolspan')}
+                >
+                  <Select.Option value="left">{this.props.dict['model.form.alignLeft']}</Select.Option>
+                  <Select.Option value="right">{this.props.dict['model.form.alignRight']}</Select.Option>
+                  <Select.Option value="center">{this.props.dict['model.form.alignCenter']}</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['model.form.columnWidth']}>
+              {getFieldDecorator('Width', {
+                initialValue: card.Width,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + this.props.dict['model.form.columnWidth'] + '!'
+                  }
+                ]
+              })(<InputNumber min={1} max={1000} precision={0} />)}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="閫夋嫨鏄剧ず鍒嗙粍锛岃〃鏍间細灞曞紑娣诲姞鍒嗙粍鐨勫瓙鍒楋紝姝ゆ椂鎺掑垪鏂瑰紡浼氬け鏁堛��">
+                <Icon type="question-circle" />
+                鏄剧ず鍒嗙粍
+              </Tooltip>
+            }>
+              {getFieldDecorator('unfold', {
+                initialValue: card.unfold || 'false'
+              })(
+                <Radio.Group>
+                  <Radio value="true">{this.props.dict['model.true']}</Radio>
+                  <Radio value="false">{this.props.dict['model.false']}</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['model.hidden']}>
+              {getFieldDecorator('Hide', {
+                initialValue: card.Hide || 'false',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + this.props.dict['model.hidden'] + '!'
+                  }
+                ]
+              })(
+                <Radio.Group>
+                  <Radio value="true">{this.props.dict['model.true']}</Radio>
+                  <Radio value="false">{this.props.dict['model.false']}</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item label={this.props.dict['header.form.order']}>
+              {getFieldDecorator('order', {
+                initialValue: card.order,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + this.props.dict['header.form.order'] + '!'
+                  }
+                ]
+              })(
+                <Select
+                  getPopupContainer={() => document.getElementById('columncolspan')}
+                >
+                  <Select.Option value="vertical">{this.props.dict['header.form.vertical']}</Select.Option>
+                  <Select.Option value="horizontal">{this.props.dict['header.form.horizontal']}</Select.Option>
+                  <Select.Option value="vertical2">{this.props.dict['header.form.vertical2']}</Select.Option>
+                  <Select.Option value="topPicBottomText">{this.props.dict['header.form.topPicBottomText']}</Select.Option>
+                  <Select.Option value="leftPicRightText">{this.props.dict['header.form.leftPicRightText']}</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <TransferForm columns={this.props.columns} ref="column-transfer" selected={card.sublist}/>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/colspanform/index.scss b/src/menu/components/table/normal-table/columncomponent/colspanform/index.scss
new file mode 100644
index 0000000..d39b484
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/colspanform/index.scss
@@ -0,0 +1,13 @@
+.commontable-cospan-column-form {
+  min-height: 190px;
+  .ant-form-item {
+    .ant-input-number {
+      width: 100%;
+    }
+  }
+  .anticon-question-circle {
+    color: #c49f47;
+    position: relative;
+    left: -3px;
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/columnform/index.jsx b/src/menu/components/table/normal-table/columncomponent/columnform/index.jsx
new file mode 100644
index 0000000..bce73f1
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/columnform/index.jsx
@@ -0,0 +1,336 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Icon, Cascader } from 'antd'
+
+import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+const columnTypeOptions = {
+  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'fieldlength', 'blacklist', 'perspective', 'rowspan'],
+  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum'],
+  link: ['label', 'field', 'type', 'nameField', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'fieldlength', 'blacklist'],
+  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'fieldlength', 'blacklist'],
+  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'fieldlength', 'blacklist', 'scale', 'maxHeight']
+}
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,     // 瀛楀吀椤�
+    formlist: PropTypes.any,
+    card: PropTypes.any,
+    inputSubmit: PropTypes.any  // 鍥炶溅鎻愪氦浜嬩欢
+  }
+
+  state = {
+    formlist: null,
+    type: '',
+    menulist: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+    let _menulist = this.props.formlist.filter(form => form.key === 'linkmenu')[0] || ''
+
+    let _options = JSON.parse(JSON.stringify(columnTypeOptions[card.type]))
+    if (card.type === 'text' || card.type === 'number') {
+      if (card.perspective !== 'linkurl') {
+        _options.push('linkmenu')
+      } else {
+        _options.push('linkurl')
+      }
+    }
+
+    this.setState({
+      type: card.type,
+      menulist: _menulist.options || [],
+      formlist: this.props.formlist.map(item => {
+        item.hidden = !_options.includes(item.key)
+
+        return item
+      })
+    })
+  }
+
+  /**
+   * @description 鍒濇娣诲姞鐨勬樉绀哄垪鍏冪礌锛岃仛鐒︽彁绀烘枃瀛�
+   */
+  componentDidMount () {
+    const { card } = this.props
+
+    if (card.focus) {
+      try {
+        let _form = document.getElementById('label')
+        _form.select()
+      } catch {
+        console.warn('琛ㄥ崟focus澶辫触锛�')
+      }
+    }
+  }
+
+  typeChange = (key, value) => {
+    const { card } = this.props
+    if (key === 'type') {
+      let _options = JSON.parse(JSON.stringify(columnTypeOptions[value]))
+
+      if (card.type === 'text' || card.type === 'number') {
+        if (card.perspective !== 'linkurl') {
+          _options.push('linkmenu')
+        } else {
+          _options.push('linkurl')
+        }
+      }
+
+      let fieldlength = 50
+
+      if (value !== 'text') {
+        fieldlength = 512
+      }
+
+      this.setState({
+        type: value,
+        formlist: this.props.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+
+          return item
+        })
+      }, () => {
+        if (this.props.form.getFieldValue('fieldlength') !== undefined) {
+          this.props.form.setFieldsValue({fieldlength: fieldlength})
+        }
+      })
+    } else if (key === 'format' && value === 'percent') {
+      this.props.form.setFieldsValue({postfix: '%'})
+    }
+  }
+
+  changeRadio = (key, value) => {
+    if (key === 'perspective') {
+      let _options = JSON.parse(JSON.stringify(columnTypeOptions[this.state.type]))
+
+      if (value !== 'linkurl') {
+        _options.push('linkmenu')
+      } else {
+        _options.push('linkurl')
+      }
+
+      this.setState({
+        formlist: this.props.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+
+          return item
+        })
+      })
+    }
+
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+    this.state.formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        let rules = []
+        if (item.key === 'field' || item.key === 'nameField') {
+          rules = [{
+            pattern: formRule.field.pattern,
+            message: formRule.field.message
+          }, {
+            max: formRule.field.max,
+            message: formRule.field.maxMessage
+          }]
+        } else if (item.key !== 'linkurl') {
+          rules = [{
+            max: formRule.input.max,
+            message: formRule.input.message
+          }]
+        }
+        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 + '!'
+                  },
+                  ...rules
+                ]
+              })(<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 + '!'
+                  }
+                ]
+              })(item.unlimit ? <InputNumber /> :
+                  <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
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.typeChange(item.key, value)}}
+                  getPopupContainer={() => document.getElementById('columnwinter')}
+                >
+                  {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.tooltip ?
+              <Tooltip placement="topLeft" overlayClassName={item.tooltipClass} title={item.tooltip}>
+                <Icon type="question-circle" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Radio.Group onChange={(e) => {this.changeRadio(item.key, e.target.value)}}>
+                  {
+                    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>
+        )
+      } else if (item.type === 'cascader') { // 澶氶��
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || []
+              })(
+                <Cascader
+                  options={this.state.menulist}
+                  placeholder=""
+                  getPopupContainer={() => document.getElementById('columnwinter')}
+                />
+              )}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          values.uuid = this.props.card.uuid
+          values.marks = this.props.card.marks || ''
+          
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="commontable-column-form" id="columnwinter">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/columnform/index.scss b/src/menu/components/table/normal-table/columncomponent/columnform/index.scss
new file mode 100644
index 0000000..fcf59ac
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/columnform/index.scss
@@ -0,0 +1,19 @@
+.commontable-column-form {
+  min-height: 190px;
+  .ant-form-item {
+    .ant-input-number {
+      width: 100%;
+    }
+  }
+  .anticon-question-circle {
+    color: #c49f47;
+    position: relative;
+    left: -3px;
+  }
+  .ant-cascader-menus {
+    padding: 5px 0px;
+    .ant-cascader-menu:last-child {
+      padding-right: 3px;
+    }
+  }
+}
diff --git a/src/menu/components/table/normal-table/columncomponent/dragcolumn/card.jsx b/src/menu/components/table/normal-table/columncomponent/dragcolumn/card.jsx
new file mode 100644
index 0000000..f98d56e
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/dragcolumn/card.jsx
@@ -0,0 +1,62 @@
+import React from 'react'
+import { useDrag, useDrop } from 'react-dnd'
+import { Icon, Popover } from 'antd'
+import './index.scss'
+
+const Card = ({ id, card, showfield, moveCard, findCard, editCard, delCard, markCard }) => {
+  const originalIndex = findCard(id).index
+  const [{ isDragging }, drag] = useDrag({
+    item: { type: 'columns', id, originalIndex },
+    collect: monitor => ({
+      isDragging: monitor.isDragging(),
+    }),
+  })
+  const [, drop] = useDrop({
+    accept: 'columns',
+    canDrop: () => true,
+    drop: (item) => {
+      const { id: draggedId, originalIndex } = item
+      
+      if (originalIndex === undefined) {
+        item.dropTargetId = id
+      } else if (draggedId && draggedId !== id) {
+        const { index: overIndex } = findCard(id)
+        moveCard(draggedId, overIndex)
+      }
+    }
+  })
+  
+  const opacity = isDragging ? 0 : 1
+
+  return (
+    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+      <div className="mk-popover-control">
+        <Icon className="edit" title="edit" type="edit" onClick={() => editCard(id)} />
+        <Icon className="close" title="delete" type="close" onClick={() => delCard(id)} />
+        {['text', 'number'].includes(card.type) && !card.origin ? <Icon className="profile" title="mark" type="ant-design" onClick={() => markCard(id)} /> : null}
+      </div>
+    } trigger="hover">
+      <div className="page-card" style={{ flex: card.Width, opacity: opacity}}>
+        <div ref={node => drag(drop(node))}>
+          <span className="ant-table-header-column">
+            <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}>
+              <span className="ant-table-column-title">{card.label}</span>
+              {card.IsSort === 'true' ?
+                <span className="ant-table-column-sorter">
+                  <Icon type="caret-up" />
+                  <Icon type="caret-down" />
+                </span> : null
+              }
+            </div>
+            {showfield ?
+              <div className="ant-table-column-fields">
+                <span className="ant-table-column-title">{card.type === 'colspan' ? card.subfield : card.field}</span>
+              </div> : null
+            }
+          </span>
+        </div>
+      </div>
+    </Popover>
+  )
+}
+export default Card
diff --git a/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.jsx b/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.jsx
new file mode 100644
index 0000000..1fa8a7c
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.jsx
@@ -0,0 +1,174 @@
+import React, { useState } from 'react'
+import { useDrop } from 'react-dnd'
+import { is, fromJS } from 'immutable'
+import update from 'immutability-helper'
+import { Icon, Popover } from 'antd'
+import Utils from '@/utils/utils.js'
+import Card from './card'
+import './index.scss'
+
+const Container = ({list, setting, gridBtn, showfield, placeholder, handleList, handleMenu, handleGridBtn, deleteMenu, markMenu }) => {
+  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)
+    delete card.focus // 鍏煎鏃╂湡鐨勫悎骞跺垪
+
+    handleMenu(card)
+  }
+  
+
+  const delCard = id => {
+    const { card } = findCard(id)
+    deleteMenu(card)
+  }
+  
+  const markCard = id => {
+    const { card } = findCard(id)
+    markMenu(card)
+  }
+
+  const [, drop] = useDrop({
+    accept: 'columns',
+    drop(item) {
+      if (item.hasOwnProperty('originalIndex')) {
+        return
+      }
+
+      let newcard = {}
+      newcard.uuid = Utils.getuuid()
+      newcard.focus = true
+      
+      newcard.Align = 'left'
+      newcard.label = 'label'
+      newcard.field = ''
+      newcard.Hide = 'false'
+      newcard.contrastType = 'static'
+      newcard.IsSort = 'true'
+      newcard.type = item.subType
+      newcard.Width = 120
+      if (item.subType === 'colspan') {
+        newcard.sublist = []
+        newcard.subfield = []
+        newcard.IsSort = 'false'
+        newcard.order = 'vertical'
+      }
+      
+      let targetId = ''
+
+      if (item.dropTargetId) {
+        targetId = item.dropTargetId
+        delete item.dropTargetId
+      } else if (cards.length > 0) {
+        targetId = cards[cards.length - 1].uuid
+      }
+
+      const { index: overIndex } = findCard(`${targetId}`)
+      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
+
+      handleList(_cards, newcard)
+    }
+  })
+
+  let columns = []
+  let _colCards = []
+
+  // 杩囨护鍚堝苟鍒�
+  let _hideCol = []
+
+  if (!showfield) {
+    cards.forEach(col => {
+      if (col.type === 'colspan' && col.sublist) {
+        _hideCol.push(...col.sublist)
+      }
+    })
+  }
+  cards.forEach(col => {
+    if (_hideCol.includes(col.uuid)) return
+
+    _colCards.push(col)
+  })
+
+  // 鏄剧ず鍒楀垎琛�
+  if (_colCards.length > 10) {
+    let number = Math.ceil(_colCards.length / Math.ceil(_colCards.length / 10))
+    for (let i = 0, len = _colCards.length; i < len; i += number) {
+      columns.push(_colCards.slice(i, i + number))
+    }
+  } else {
+    columns.push(_colCards)
+  }
+
+  return (
+    <div ref={drop} className="ant-row">
+      {columns.map((column, i) => (
+        <div key={i} className="column-box">
+          {/* 澶氶�� */}
+          {i === 0 && column.length > 0 && setting.tableType === 'checkbox' ?
+            <div className="page-card" style={{flex: 60}}>
+              <span className="ant-checkbox-inner"></span>
+            </div> : null
+          }
+          {/* 鍗曢�� */}
+          {i === 0 && column.length > 0 && setting.tableType === 'radio' ?
+            <div className="page-card" style={{flex: 60}}></div> : null
+          }
+          {column.map(card => (
+            <Card
+              key={card.uuid}
+              id={card.uuid}
+              card={card}
+              showfield={showfield}
+              moveCard={moveCard}
+              editCard={editCard}
+              delCard={delCard}
+              markCard={markCard}
+              findCard={findCard}
+            />
+          ))}
+          {i === (columns.length - 1) && gridBtn && gridBtn.display ?
+            <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+              <div className="mk-popover-control">
+                <Icon className="edit" type="edit" onClick={handleGridBtn}/>
+              </div>
+            } trigger="hover">
+              <div className="page-card" style={{flex: gridBtn.Width}}>
+                <div style={{cursor: 'default'}}>
+                  <span className="ant-table-header-column">
+                    <div className="ant-table-column-sorters" title={gridBtn.label} style={{textAlign: gridBtn.Align}}>
+                      <span className="ant-table-column-title">{gridBtn.label}</span>
+                    </div>
+                  </span>
+                </div>
+              </div>
+            </Popover> : null
+          }
+        </div>
+      ))}
+      
+      {cards.length === 0 ?
+        <div className="common-drawarea-placeholder">
+          {placeholder}
+        </div> : null
+      }
+    </div>
+  )
+}
+export default Container
diff --git a/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.scss b/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.scss
new file mode 100644
index 0000000..1bbed5f
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/dragcolumn/index.scss
@@ -0,0 +1,6 @@
+.common-drawarea-placeholder {
+  width: 100%;
+  line-height: 65px;
+  text-align: center;
+  color: #bcbcbc;
+}
diff --git a/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.jsx b/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.jsx
new file mode 100644
index 0000000..ccbb363
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.jsx
@@ -0,0 +1,218 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, InputNumber, Radio } from 'antd'
+import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,     // 瀛楀吀椤�
+    card: PropTypes.any,
+    inputSubmit: PropTypes.any  // 鍥炶溅鎻愪氦浜嬩欢
+  }
+
+  state = {
+    formlist: [
+      {
+        type: 'text',
+        key: 'label',
+        label: this.props.dict['model.name'],
+        initVal: this.props.card.label,
+        required: true
+      },
+      {
+        type: 'select',
+        key: 'Align',
+        label: this.props.dict['model.form.align'],
+        initVal: this.props.card.Align,
+        required: true,
+        options: [{
+          MenuID: 'left',
+          text: this.props.dict['model.form.alignLeft']
+        }, {
+          MenuID: 'right',
+          text: this.props.dict['model.form.alignRight']
+        }, {
+          MenuID: 'center',
+          text: this.props.dict['model.form.alignCenter']
+        }]
+      },
+      {
+        type: 'number',
+        key: 'Width',
+        decimal: 0,
+        label: this.props.dict['model.form.columnWidth'],
+        initVal: this.props.card.Width,
+        required: true
+      },
+      // {
+      //   type: 'select',
+      //   key: 'style',
+      //   label: this.props.dict['model.form.style'],
+      //   initVal: this.props.card.style,
+      //   required: true,
+      //   options: [{
+      //     MenuID: 'button',
+      //     text: this.props.dict['header.form.button']
+      //   }, {
+      //     MenuID: 'text',
+      //     text: this.props.dict['model.form.href']
+      //   }]
+      // },
+      // {
+      //   type: 'select',
+      //   key: 'show',
+      //   label: this.props.dict['header.form.order'],
+      //   initVal: this.props.card.show,
+      //   required: true,
+      //   options: [{
+      //     MenuID: 'horizontal',
+      //     text: this.props.dict['header.form.horizontal']
+      //   }, {
+      //     MenuID: 'vertical',
+      //     text: this.props.dict['header.form.vertical']
+      //   }]
+      // }
+    ]
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+    this.state.formlist.forEach((item, index) => {
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  },
+                  {
+                    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.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<InputNumber min={1} max={1000} 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
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  getPopupContainer={() => document.getElementById('gridbtncolumnwinter')}
+                >
+                  {item.options.map(option =>
+                    <Select.Option id={option.MenuID} title={option.text} key={option.MenuID} value={option.MenuID}>
+                      {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.MenuID} value={option.MenuID}>{option.text}</Radio>
+                      )
+                    })
+                  }
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve({...this.props.card, ...values})
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="commontable-gridbtn-column-form" id="gridbtncolumnwinter">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.scss b/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.scss
new file mode 100644
index 0000000..abb563c
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/gridbtnform/index.scss
@@ -0,0 +1,8 @@
+.commontable-gridbtn-column-form {
+  min-height: 190px;
+  .ant-form-item {
+    .ant-input-number {
+      width: 100%;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/index.jsx b/src/menu/components/table/normal-table/columncomponent/index.jsx
new file mode 100644
index 0000000..ea1c143
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/index.jsx
@@ -0,0 +1,509 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Modal, notification, Switch, message, Spin } from 'antd'
+
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import { getColumnForm } from '@/templates/zshare/formconfig'
+
+import ColumnForm from './columnform'
+import ColspanForm from './colspanform'
+import GridBtnForm from './gridbtnform'
+import DragElement from './dragcolumn'
+import MarkColumn from './markcolumn'
+import './index.scss'
+
+const { confirm } = Modal
+
+class ColumnComponent extends Component {
+  static propTpyes = {
+    config: PropTypes.object,        // 閰嶇疆淇℃伅
+    updatecolumn: PropTypes.func     // 鏇存柊
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    columnlist: null,    // 鏄剧ず鍒�
+    loading: false,      // 鏌ヨ鏄剧ず鍒楄仈鍔ㄨ彍鍗�
+    showField: false,    // 鏄剧ず鍒楀瓧娈�
+    modaltype: '',       // 妯℃�佹鎺у埗
+    card: null           // 缂栬緫涓厓绱�
+  }
+
+  /**
+   * @description 鏄剧ず鍒楀垵濮嬪寲
+   */
+  UNSAFE_componentWillMount () {
+    this.setState({
+      columnlist: fromJS(this.props.config.cols).toJS()
+    })
+  }
+
+  /**
+   * @description 鐩戝惉鍒版樉绀哄垪澶嶅埗鏃讹紝瑙﹀彂鏄剧ず鍒楃紪杈�
+   */
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    const { config } = this.props
+    const { columnlist } = this.state
+
+    if (!is(fromJS(nextProps.config.cols), fromJS(config.cols)) && !is(fromJS(nextProps.config.cols), fromJS(columnlist))) {
+      this.setState({columnlist: fromJS(nextProps.config.cols).toJS()})
+    }
+  }
+
+  /**
+   * @description 鏄剧ず鍒楅『搴忚皟鏁达紝鎴栨嫋鎷芥坊鍔�
+   */
+  handleList = (list, card) => {
+    const { config } = this.props
+
+    if (card) {
+      this.setState({columnlist: list})
+      this.handleColumn(card)
+    } else {
+      this.setState({columnlist: list}, ()=> {     
+        this.props.updatecolumn({...config, cols: list})
+      })
+    }
+  }
+
+  /**
+   * @description 鏄剧ず鍒椾笌鍚堝苟鍒楃紪杈戯紝鑾峰彇琛ㄥ崟淇℃伅
+   */
+  handleColumn = (card) => {
+    if (card.type !== 'colspan') {
+      let menulist = sessionStorage.getItem('fstMenuList')
+      if (menulist) {
+        try {
+          menulist = JSON.parse(menulist)
+        } catch {
+          menulist = []
+        }
+      } else {
+        menulist = []
+      }
+      
+      this.setState({
+        modaltype: 'cols',
+        card: card,
+        formlist: getColumnForm(card, menulist)
+      })
+    } else {
+      this.setState({
+        modaltype: 'colspan',
+        card: card
+      })
+    }
+  }
+
+  /**
+   * @description 璁剧疆鏍囧織
+   */
+  markElement = (card) => {
+    this.setState({
+      modaltype: 'mark',
+      card: card
+    })
+  }
+
+  /**
+   * @description 鎿嶄綔鍒楃紪杈�
+   */
+  handleGridBtn = () => {
+    this.setState({
+      modaltype: 'gridbtn'
+    })
+  }
+
+  /**
+   * @description 鍙栨秷淇濆瓨锛屽鏋滃厓绱犱负鏂版坊鍏冪礌锛屽垯浠庡簭鍒椾腑鍒犻櫎
+   */
+  editModalCancel = () => {
+    const { card } = this.state
+    
+    if (card && card.focus) {
+      let _columnlist = fromJS(this.state.columnlist).toJS()
+
+      _columnlist = _columnlist.filter(item => item.uuid !== card.uuid)
+
+      this.setState({
+        card: null,
+        modaltype: '',
+        columnlist: _columnlist
+      })
+    } else {
+      this.setState({
+        card: null,
+        modaltype: ''
+      })
+    }
+  }
+
+  /**
+   * @description 鎼滅储淇敼鍚庢彁浜や繚瀛�
+   * 1銆佸幓闄ょ郴缁熼粯璁ゆ樉绀哄垪
+   * 2銆佸瓧娈靛強鎻愮ず鏂囧瓧閲嶅鏍¢獙
+   * 3銆佹洿鏂颁笅鎷夎彍鍗曞彲閫夐泦鍚�
+   * 4銆佷笅鎷夎彍鍗曟暟鎹簮璇硶楠岃瘉
+   */
+  handleSubmit = () => {
+    const { config } = this.props
+    const { modaltype, card } = this.state
+
+    let _columnlist = fromJS(this.state.columnlist).toJS()
+
+    if (modaltype === 'cols' || modaltype === 'colspan') {
+      this.columnFormRef.handleConfirm().then(res => {
+        let fieldrepet = false // 瀛楁閲嶅
+        let labelrepet = false // 鎻愮ず鏂囧瓧閲嶅
+        let rowspanLabel = ''  // 宸插瓨鍦ㄧ殑琛屽悎骞跺瓧娈�
+
+        _columnlist = _columnlist.filter(item => !item.origin || item.uuid === res.uuid) // 鍘婚櫎鍒濆鍒�
+        _columnlist = _columnlist.map(item => {
+          if (item.uuid !== res.uuid && res.field && item.field) {
+            if (item.field === res.field) {
+              fieldrepet = true
+            } else if (item.label === res.label) {
+              labelrepet = true
+            } else if (res.rowspan === 'true' && item.rowspan === 'true') {
+              rowspanLabel = item.label
+            }
+          }
+
+          if (item.uuid === res.uuid) {
+            return res
+          } else {
+            return item
+          }
+        })
+
+        if (fieldrepet) {
+          notification.warning({
+            top: 92,
+            message: this.state.dict['model.field.exist'] + ' !',
+            duration: 5
+          })
+          return
+        } else if (labelrepet) {
+          notification.warning({
+            top: 92,
+            message: this.state.dict['model.name.exist'] + ' !',
+            duration: 5
+          })
+          return
+        } else if (rowspanLabel) {
+          notification.warning({
+            top: 92,
+            message: `宸插瓨鍦ㄨ鍚堝苟瀛楁銆�${rowspanLabel}銆�!`,
+            duration: 5
+          })
+          return
+        }
+
+        if (!card.focus && (card.type !== res.type || (res.field && card.field !== res.field))) {
+          let refers = []
+          _columnlist.forEach(column => {
+            if (column.marks && column.marks.filter(mark => mark.field === card.field || mark.contrastField === card.field).length > 0) {
+              refers.push(column.label)
+            }
+            if (column.type === 'colspan') {
+              let _length = column.sublist.length
+              column.sublist = column.sublist.filter(cell => cell !== card.uuid)
+
+              if (column.sublist.length < _length) {
+                let subfield = []  // 鍚堝苟鍒楀瓧娈�
+                _columnlist.forEach(col => {
+                  if (col.field && column.sublist.includes(col.uuid)) {
+                    subfield.push(col.field)
+                  }
+                })
+                column.subfield = subfield.join(', ')
+              }
+            }
+          })
+
+          if (refers.length > 0) {
+            notification.warning({
+              top: 92,
+              message: '鏄剧ず鍒椼��' + refers.join('銆�') + '銆嬫爣璁颁腑鍚湁璇ュ瓧娈碉紝姝ゆ淇敼浼氬鑷存爣璁板け鏁堬紝璇蜂慨鏀圭浉搴旂殑鏍囪璁剧疆锛�',
+              duration: 5
+            })
+          }
+        }
+
+        this.setState({
+          card: null,
+          columnlist: _columnlist,
+          modaltype: ''
+        }, ()=> {
+          this.props.updatecolumn({...config, cols: _columnlist})
+        })
+      })
+    } else if (modaltype === 'gridbtn') {
+      this.gridBtnFormRef.handleConfirm().then(res => {
+        this.setState({
+          modaltype: ''
+        })
+
+        this.props.updatecolumn({...config, gridBtn: res})
+      })
+    }
+  }
+
+  /**
+   * @description 鏄剧ず鍒楀垹闄�
+   */
+  deleteElement = (card) => {
+    const { config } = this.props
+    const { dict } = this.state
+    let _this = this
+
+    confirm({
+      content: dict['model.confirm'] + dict['model.delete'] + ` - ${card.label} 锛焋,
+      onOk() {
+        let _columnlist = fromJS(_this.state.columnlist).toJS()
+
+        _columnlist = _columnlist.filter(item => item.uuid !== card.uuid)
+
+        if (card.field) {
+          let refers = []
+          _columnlist.forEach(column => {
+            if (column.marks && column.marks.filter(mark => mark.field === card.field || mark.contrastField === card.field).length > 0) {
+              refers.push(column.label)
+            }
+            if (column.type === 'colspan') {
+              let _length = column.sublist.length
+              column.sublist = column.sublist.filter(cell => cell !== card.uuid)
+
+              if (column.sublist.length < _length) {
+                let subfield = []  // 鍚堝苟鍒楀瓧娈�
+                _columnlist.forEach(col => {
+                  if (col.field && column.sublist.includes(col.uuid)) {
+                    subfield.push(col.field)
+                  }
+                })
+                column.subfield = subfield.join(', ')
+              }
+            }
+          })
+
+          if (refers.length > 0) {
+            notification.warning({
+              top: 92,
+              message: '鏄剧ず鍒椼��' + refers.join('銆�') + '銆嬫爣璁颁腑鍚湁璇ュ瓧娈碉紝鍒犻櫎浼氬鑷存爣璁板け鏁堬紝璇蜂慨鏀圭浉搴旂殑鏍囪璁剧疆锛�',
+              duration: 5
+            })
+          }
+        }
+
+        _this.setState({
+          columnlist: _columnlist
+        }, ()=> {
+          _this.props.updatecolumn({...config, cols: _columnlist})
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 鏄剧ず鍒楀鍒�
+   */
+  copycolumn = () => {
+    const { columnlist } = this.state
+
+    let oInput = document.createElement('input')
+    let val = {
+      copyType: 'columns',
+      columns: columnlist
+    }
+
+    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
+    document.body.appendChild(oInput)
+    oInput.select()
+    document.execCommand('Copy')
+    oInput.className = 'oInput'
+    oInput.style.display = 'none'
+
+    message.success('澶嶅埗鎴愬姛銆�')
+
+    document.body.removeChild(oInput)
+  }
+
+  /**
+   * @description 鏄剧ず鍒楀瓧娈靛悕鏄剧ず鎴栭殣钘忔帶鍒�
+   */
+  onFieldChange = () => {
+    const { showField, columnlist } = this.state
+
+    if (!showField) {
+      let fields = []
+      columnlist.forEach(col => {
+        if (col.field) {
+          fields.push(col.field)
+        }
+      })
+
+      fields = fields.join(',')
+
+      let textArea = document.createElement('textarea')
+      textArea.value = fields
+      document.body.appendChild(textArea)
+      textArea.select()
+
+      try {
+        document.execCommand('copy')
+        document.body.removeChild(textArea)
+      } catch (err) {
+        document.body.removeChild(textArea)
+      }
+    }
+
+    this.setState({
+      showField: !showField
+    })
+  }
+
+  markSubmit = () => {
+    const { config } = this.props
+    const { card } = this.state
+    let _columnlist = fromJS(this.state.columnlist).toJS()
+    let _marks = this.refs.markRef.state.marks
+
+    if (_marks.length === 0) {
+      _marks = ''
+    }
+
+    _columnlist = _columnlist.map(item => {
+      if (item.uuid === card.uuid) {
+        item.marks = _marks
+      }
+        
+      return item
+    })
+
+    this.setState({
+      card: null,
+      columnlist: _columnlist,
+      modaltype: ''
+    }, ()=> { 
+      this.props.updatecolumn({...config, cols: _columnlist})
+    })
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { config } = this.props
+    const { modaltype, columnlist, dict, card } = this.state
+
+    return (
+      <div className="model-custom-table-column-list">
+        {columnlist && columnlist.length > 0 ?
+          <Icon className="column-copy" title="copy" type="copy" onClick={this.copycolumn} /> : null
+        }
+        <Switch checkedChildren={dict['model.switch.open']} unCheckedChildren={dict['model.switch.close']} defaultChecked={this.state.showField} onChange={this.onFieldChange} />
+        <DragElement
+          list={columnlist}
+          setting={config.setting}
+          gridBtn={config.gridBtn}
+          handleList={this.handleList}
+          handleMenu={this.handleColumn}
+          deleteMenu={this.deleteElement}
+          markMenu={this.markElement}
+          handleGridBtn={this.handleGridBtn}
+          showfield={this.state.showField}
+          placeholder={this.state.dict['header.form.column.placeholder']}
+        />
+        {/* 鏄剧ず鍒楃紪杈� */}
+        <Modal
+          title={dict['header.modal.column.edit']}
+          visible={modaltype === 'cols'}
+          width={800}
+          maskClosable={false}
+          onOk={this.handleSubmit}
+          onCancel={this.editModalCancel}
+          destroyOnClose
+        >
+          <ColumnForm
+            dict={dict}
+            card={card}
+            inputSubmit={this.handleSubmit}
+            formlist={this.state.formlist}
+            wrappedComponentRef={(inst) => this.columnFormRef = inst}
+          />
+        </Modal>
+        {/* 鍚堝苟鍒楃紪杈� */}
+        <Modal
+          title={dict['model.form.colspan'] + '-' + dict['model.edit']}
+          visible={modaltype === 'colspan'}
+          width={800}
+          maskClosable={false}
+          onOk={this.handleSubmit}
+          onCancel={this.editModalCancel}
+          destroyOnClose
+        >
+          <ColspanForm
+            dict={dict}
+            card={card}
+            inputSubmit={this.handleSubmit}
+            columns={columnlist}
+            wrappedComponentRef={(inst) => this.columnFormRef = inst}
+          />
+        </Modal>
+        {/* 鎿嶄綔鍒楃紪杈� */}
+        <Modal
+          title={dict['header.modal.gridbtn.edit']}
+          visible={modaltype === 'gridbtn'}
+          width={800}
+          maskClosable={false}
+          onOk={this.handleSubmit}
+          onCancel={this.editModalCancel}
+          destroyOnClose
+        >
+          <GridBtnForm
+            dict={dict}
+            inputSubmit={this.handleSubmit}
+            card={config.gridBtn}
+            wrappedComponentRef={(inst) => this.gridBtnFormRef = inst}
+          />
+        </Modal>
+        {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
+        <Modal
+          wrapClassName="model-table-column-mark-modal"
+          title={'鏍囪璁剧疆'}
+          visible={modaltype === 'mark'}
+          width={'75vw'}
+          maskClosable={false}
+          style={{minWidth: '900px', maxWidth: '1200px'}}
+          okText={dict['model.submit']}
+          onOk={this.markSubmit}
+          onCancel={() => { this.setState({ modaltype: '' }) }}
+          destroyOnClose
+        >
+          <MarkColumn
+            ref="markRef"
+            card={card}
+            dict={dict}
+            columns={columnlist}
+          />
+        </Modal>
+        {this.state.loading && <Spin size="large" />}
+      </div>
+    )
+  }
+}
+
+export default ColumnComponent
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/index.scss b/src/menu/components/table/normal-table/columncomponent/index.scss
new file mode 100644
index 0000000..707fe37
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/index.scss
@@ -0,0 +1,99 @@
+.model-custom-table-column-list {
+  position: relative;
+  padding: 0px 0px 50px;
+
+  .ant-switch {
+    position: absolute;
+    right: 5px;
+    top: -25px;
+  }
+  .column-copy {
+    position: absolute;
+    font-size: 16px;
+    right: 70px;
+    top: -22px;
+    color: #26C281;
+    cursor: pointer;
+  }
+  > .ant-row {
+    background: #fafafa;
+    border-radius: 4px;
+    min-height: 47px;
+    border: 1px solid #e8e8e8;
+    .column-box {
+      display: flex;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    .column-box:not(:first-child) {
+      border-top: 1px solid #e8e8e8;
+    }
+    .page-card {
+      position: relative;
+      padding: 0px;
+      min-height: 45px;
+      > div {
+        padding: 12px 0px 0px;
+        cursor: move;
+        height: 100%;
+        .ant-table-column-sorters {
+          padding: 0px 8px 12px;
+          // white-space: nowrap;
+        }
+        .ant-table-column-fields {
+          padding: 0px 8px 5px;
+        }
+      }
+      .ant-table-column-sorter {
+        position: relative;
+        display: inline-block;
+        width: 24px;
+        font-size: 12px;
+        color: #bfbfbf;
+        .anticon-caret-up {
+          position: relative;
+          left: 10px;
+          top: -3px;
+        }
+        .anticon-caret-down {
+          position: relative;
+          left: -2px;
+          top: 3px;
+        }
+      }
+      .ant-checkbox-inner {
+        margin-top: 14px;
+        margin-left: calc(50% - 8px);
+      }
+    }
+    .page-card:not(:last-child) {
+      border-right: 1px solid #e8e8e8;
+    }
+  }
+}
+
+.model-table-column-mark-modal {
+  .ant-modal {
+    top: 50px;
+    padding-bottom: 5px;
+    .ant-modal-body {
+      max-height: calc(100vh - 190px);
+      min-height: 350px;
+      overflow-y: auto;
+    }
+    .ant-modal-body::-webkit-scrollbar {
+      width: 7px;
+    }
+    .ant-modal-body::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+      background: rgba(0, 0, 0, 0.13);
+    }
+    .ant-modal-body::-webkit-scrollbar-track {
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+      border-radius: 3px;
+      border: 1px solid rgba(0, 0, 0, 0.07);
+      background: rgba(0, 0, 0, 0);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/markcolumn/index.jsx b/src/menu/components/table/normal-table/columncomponent/markcolumn/index.jsx
new file mode 100644
index 0000000..f98be64
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/markcolumn/index.jsx
@@ -0,0 +1,242 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { fromJS } from 'immutable'
+import { Table, Popconfirm, Icon } from 'antd'
+
+import Utils from '@/utils/utils.js'
+
+import MarkForm from './markform'
+import './index.scss'
+import '@/assets/css/table.scss'
+
+class MarkColumn extends Component {
+  static propTpyes = {
+    columns: PropTypes.array,  // 鏄剧ず鍒�
+    dict: PropTypes.object,    // 瀛楀吀椤�
+    card: PropTypes.object,
+  }
+
+  state = {
+    marks: null,
+    columns: null,
+    markColumns: [
+      {
+        title: '瀛楁',
+        dataIndex: 'field',
+        width: '20%',
+        render: (text, record) => {
+          let item = this.props.columns.filter(col => col.field === record.field)[0]
+          if (item) {
+            return item.label + '锛�' + item.field + '锛�'
+          } else {
+            return ''
+          }
+        }
+      },
+      {
+        title: '瀵规瘮绫诲瀷',
+        dataIndex: 'contrastType',
+        width: '15%',
+        render: (text, record) => {
+          if (record.contrastType === 'static') {
+            return '闈欐��'
+          } else {
+            return '鍔ㄦ��'
+          }
+        }
+      },
+      {
+        title: '瀵规瘮鍊�/瀛楁',
+        dataIndex: 'contrastValue',
+        width: '20%',
+        render: (text, record) => {
+          if (record.contrastType === 'static') {
+            return '瀵规瘮鍊�: ' + text
+          } else {
+            let item = this.props.columns.filter(col => col.field === record.contrastField)[0]
+            if (item) {
+              return '瀛楁: ' + item.label + '锛�' + item.field + '锛�'
+            } else {
+              return ''
+            }
+          }
+        }
+      },
+      {
+        title: '瀵规瘮鏂瑰紡',
+        dataIndex: 'match',
+        width: '12%'
+      },
+      {
+        title: '鏍囪鏁堟灉',
+        dataIndex: 'signType',
+        width: '13%',
+        render: (text, record) => {
+          let item = this.props.columns.filter(col => col.field === record.field)[0]
+          if (!item) return ''
+
+          let content = ''
+          if (item.type === 'text') {
+            content = '鏂囨湰'
+          } else {
+            content = Math.ceil(Math.random() * 100) * 10
+          }
+
+          let _outerclass = ''
+          if (record.signType === 'font') {
+            _outerclass = 'font ' + record.color[1]
+          } else if (record.signType === 'background') {
+            _outerclass = 'background ' + record.color[1]
+          } else if (record.signType === 'card') {
+            _outerclass = 'background ' + record.color[1]
+            content = '鏁堟灉鍦ㄥ崱鐗囦腑鍙'
+          } else if (record.signType === 'icon') {
+            if (record.position === 'front') {
+              content = <div><Icon className={'font ' + record.color[1]} type={record.icon} /> {content} </div>
+            } else {
+              content = <div> {content} <Icon className={'font ' + record.color[1]} type={record.icon} /> </div>
+            }
+          }
+
+          return <div className={_outerclass}>
+            <div className="baseboard"></div>
+            <div className="content">
+              {content}
+            </div>
+          </div>
+        }
+      },
+      {
+        title: '鎿嶄綔',
+        align: 'center',
+        dataIndex: 'operation',
+        render: (text, record) =>
+          (
+            <div>
+              <span className="operation-btn" title={this.props.dict['model.edit']} onClick={() => this.handleEdit(record)} style={{color: '#1890ff'}}><Icon type="edit" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.up']} onClick={() => this.handleUpDown(record, 'up')} style={{color: '#1890ff'}}><Icon type="arrow-up" /></span>
+              <span className="operation-btn" title={this.props.dict['header.form.down']} onClick={() => this.handleUpDown(record, 'down')} style={{color: '#ff4d4f'}}><Icon type="arrow-down" /></span>
+              <Popconfirm
+                overlayClassName="popover-confirm"
+                title={this.props.dict['model.query.delete']}
+                onConfirm={() => this.handleDelete(record)
+              }>
+                <span className="operation-btn" style={{color: '#ff4d4f'}}><Icon type="delete" /></span>
+              </Popconfirm>
+            </div>
+          )
+      }
+    ]
+  }
+
+  UNSAFE_componentWillMount() {
+    const { columns, card } = this.props
+
+    this.setState({
+      columns: columns.filter(col => col.type === 'text' || col.type === 'number'),
+      marks: card.marks ? fromJS(card.marks).toJS() : []
+    })
+  }
+
+  markChange = (values) => {
+    let _marks = fromJS(this.state.marks).toJS()
+
+    if (values.uuid) {
+      _marks = _marks.map(item => {
+        if (item.uuid === values.uuid) {
+          return values
+        } else {
+          return item
+        }
+      })
+    } else {
+      values.uuid = Utils.getuuid()
+      _marks.push(values)
+    }
+
+    this.setState({
+      marks: _marks
+    })
+  }
+
+  handleDelete = (record) => {
+    const { marks } = this.state
+
+    let _marks = marks.filter(item => item.uuid !== record.uuid)
+    
+    this.setState({ marks: _marks })
+  }
+
+  handleEdit = (record) => {
+    this.markForm.edit(record)
+    
+    let node = document.getElementById('mark-column-box-modal').parentNode
+
+    if (node && node.scrollTop) {
+      let inter = Math.ceil(node.scrollTop / 10)
+
+      let timer = setInterval(() => {
+        if (node.scrollTop - inter > 0) {
+          node.scrollTop = node.scrollTop - inter
+        } else {
+          node.scrollTop = 0
+          clearInterval(timer)
+        }
+      }, 10)
+    }
+  }
+
+  handleUpDown = (record, direction) => {
+    let _marks = fromJS(this.state.marks).toJS()
+    let index = 0
+
+    _marks = _marks.filter((item, i) => {
+      if (item.uuid === record.uuid) {
+        index = i
+      }
+
+      return item.uuid !== record.uuid
+    })
+    if ((index === 0 && direction === 'up') || (index === _marks.length && direction === 'down')) {
+      return
+    }
+
+    if (direction === 'up') {
+      _marks.splice(index - 1, 0, record)
+    } else {
+      _marks.splice(index + 1, 0, record)
+    }
+
+    this.setState({
+      marks: _marks
+    })
+  }
+
+  render() {
+    const { card } = this.props
+    const { marks, markColumns, columns } = this.state
+
+    return (
+      <div id="mark-column-box-modal" className="">
+        <MarkForm
+          dict={this.props.dict}
+          card={card}
+          columns={columns}
+          markChange={this.markChange}
+          wrappedComponentRef={(inst) => this.markForm = inst}
+        />
+        <Table
+          bordered
+          rowKey="uuid"
+          className="mingke-table"
+          dataSource={marks}
+          rowClassName={(record) => record.signType === 'line' ? 'mk-table-line background ' + record.color[1] : ''}
+          columns={markColumns}
+          pagination={false}
+        />
+      </div>
+    )
+  }
+}
+
+export default MarkColumn
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/markcolumn/index.scss b/src/menu/components/table/normal-table/columncomponent/markcolumn/index.scss
new file mode 100644
index 0000000..3502583
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/markcolumn/index.scss
@@ -0,0 +1,67 @@
+#mark-column-box-modal {
+  .ant-form-item-label .anticon-question-circle {
+    color: #c49f47;
+    position: relative;
+    left: -3px;
+  }
+  table tr td {
+    word-wrap: break-word;
+    word-break: break-word;
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+  
+  .mingke-table .ant-empty {
+    margin: 20px 8px!important;
+  }
+  .mingke-table {
+    td {
+      position: relative;
+    }
+  }
+  .errorval {
+    display: inline-block;
+    width: 30px;
+  }
+  .operation-btn {
+    display: inline-block;
+    font-size: 16px;
+    padding: 0 5px;
+    cursor: pointer;
+  }
+  .ant-tabs-tabpane {
+    position: relative;
+    .excel-col-add {
+      position: absolute;
+      right: 0;
+      top: 90px;
+    }
+  }
+
+  .ant-table-tbody tr.background td {
+    background: unset!important;
+  }
+  .background {
+    .baseboard {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+    }
+    .content {
+      position: relative;
+    }
+  }
+
+  .mk-table-line.background {
+    .baseboard {
+      background: unset!important;
+    }
+  }
+
+  .ant-form-item {
+    white-space: nowrap;
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.jsx b/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.jsx
new file mode 100644
index 0000000..07d195f
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.jsx
@@ -0,0 +1,384 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Select, Button, Input, InputNumber, Radio, Icon, Cascader, Tooltip } from 'antd'
+
+import { minkeColorSystem, minkeIconSystem } from '@/utils/option.js'
+import './index.scss'
+
+class UniqueForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,         // 瀛楀吀椤�
+    card: PropTypes.object,         // 瀛楁淇℃伅
+    columns: PropTypes.array,       // 鍒楀悕闆嗗悎
+    markChange: PropTypes.func      // 淇敼鍑芥暟
+  }
+
+  state = {
+    editItem: null, // 缂栬緫鍏冪礌
+    contrastType: 'static',
+    originField: this.props.card,
+    signType: 'background',
+    selectIcon: '',
+    options: JSON.parse(JSON.stringify(minkeColorSystem)),
+    icons: minkeIconSystem.direction
+  }
+
+  UNSAFE_componentWillMount() {
+    this.setState({
+      options: this.state.options.map(option => {
+        option.children = option.children.map(cell => {
+          cell.label = <div className={'background ' + cell.value}>{cell.value}</div>
+
+          return cell
+        })
+        return option
+      })
+    })
+  }
+
+  edit = (record) => {
+    const { columns } = this.props
+    let item = columns.filter(col => col.field === record.field)[0]
+
+    let _type = 'background '
+    if (record.signType === 'icon' || record.signType === 'font') {
+      _type = 'font '
+    }
+
+    this.setState({
+      originField: item || '',
+      editItem: record,
+      contrastType: record.contrastType || '',
+      signType: record.signType || '',
+      selectIcon: record.icon || '',
+      options: this.state.options.map(option => {
+        option.children = option.children.map(cell => {
+          cell.label = <div className={_type + cell.value}>{record.icon ? <Icon type={record.icon} /> : cell.value}</div>
+
+          return cell
+        })
+        return option
+      })
+    }, () => {
+      let fieldvalue = {}
+      Object.keys(record).forEach(key => {
+        if (this.props.form.getFieldValue(key) !== undefined) {
+          fieldvalue[key] = record[key]
+        }
+      })
+
+      this.props.form.setFieldsValue(fieldvalue)
+    })
+  }
+
+  /**
+   * @description 瀛楁鍒囨崲
+   */
+  fieldChange = (value) => {
+    const { columns } = this.props
+    let item = columns.filter(col => col.field === value)[0]
+
+    this.setState({
+      originField: item
+    })
+
+    if (this.state.contrastType !== 'static') {
+      this.props.form.setFieldsValue({contrastField: ''})
+    } else {
+      this.props.form.setFieldsValue({contrastValue: ''})
+    }
+  }
+
+  /**
+   * @description 瀵规瘮鍊肩被鍨嬪垏鎹�
+   */
+  changeType = (val) => {
+    this.setState({
+      contrastType: val
+    })
+  }
+
+  /**
+   * @description 鏍囪绫诲瀷鍒囨崲
+   */
+  changeSignType = (val) => {
+    let _type = 'background '
+    if (val === 'icon' || val === 'font') {
+      _type = 'font '
+    }
+
+    let newState = {
+      signType: val,
+      selectIcon: ''
+    }
+
+    if (val !== 'icon') {
+      newState.options = this.state.options.map(option => {
+        option.children = option.children.map(cell => {
+          cell.label = <div className={_type + cell.value}>{cell.value}</div>
+
+          return cell
+        })
+        return option
+      })
+    }
+
+    this.setState(newState)
+  }
+
+  /**
+   * @description 鍥炬爣绫诲瀷鍒囨崲
+   */
+  changeIconType = (val) => {
+    this.setState({
+      icons: minkeIconSystem[val],
+      selectIcon: ''
+    })
+    this.props.form.setFieldsValue({icon: ''})
+  }
+
+  /**
+   * @description 鍒囨崲鍥炬爣
+   */
+  changeIcon = (val) => {
+    this.setState({
+      selectIcon: val,
+      options: this.state.options.map(option => {
+        option.children = option.children.map(cell => {
+          cell.label = <div className={'font ' + cell.value}><Icon type={val} /></div>
+
+          return cell
+        })
+        return option
+      })
+    })
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        values.uuid = this.state.editItem ? this.state.editItem.uuid : ''
+
+        this.props.markChange(values)
+        this.setState({
+          editItem: null
+        })
+      }
+    })
+  }
+
+  render() {
+    const { columns } = this.props
+    const { originField, contrastType, signType, options, selectIcon, icons } = this.state
+    const { getFieldDecorator } = this.props.form
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    let contFields = columns.filter(col => originField.field !== col.field && originField.type === col.type)
+
+    return (
+      <Form {...formItemLayout} id="model-mark-form-box" className="mingke-table">
+        <Row gutter={24}>
+          <Col span={6}>
+            <Form.Item label={'瀛楁'}>
+              {getFieldDecorator('field', {
+                initialValue: originField.field,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '瀛楁!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={this.fieldChange}
+                >
+                  {columns.map(item => (
+                    <Select.Option key={item.uuid} title={item.label + '(' + item.field + ')'} value={item.field}>{item.label + '(' + item.field + ')'}</Select.Option>
+                  ))}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={6}>
+            <Form.Item label={'瀵规瘮绫诲瀷'}>
+              {getFieldDecorator('contrastType', {
+                initialValue: 'static'
+              })(
+                <Radio.Group onChange={(e) => this.changeType(e.target.value)}>
+                  <Radio value="static">闈欐��</Radio>
+                  <Radio value="dynamic">鍔ㄦ��</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+          <Col span={6}>
+            <Form.Item label={'瀵规瘮鏂瑰紡'}>
+              {getFieldDecorator('match', {
+                initialValue: '=',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '瀵规瘮鏂瑰紡!'
+                  }
+                ]
+              })(
+                <Select>
+                  <Select.Option value="="> = </Select.Option>
+                  <Select.Option value="!="> != </Select.Option>
+                  {originField.type === 'number' ? <Select.Option value=">"> > </Select.Option> : null}
+                  {originField.type === 'number' ? <Select.Option value="<"> &lt; </Select.Option> : null}
+                  {originField.type === 'text' ? <Select.Option value="like"> like </Select.Option> : null}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          {contrastType === 'static' ? <Col span={6}>
+            <Form.Item label={'瀵规瘮鍊�'}>
+              {getFieldDecorator('contrastValue', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '瀵规瘮鍊�!'
+                  }
+                ]
+              })(originField.type === 'number' ? <InputNumber /> : <Input placeholder="" autoComplete="off" />)}
+            </Form.Item>
+          </Col> : null}
+          {contrastType === 'dynamic' ? <Col span={6}>
+            <Form.Item label={'瀵规瘮瀛楁'}>
+              {getFieldDecorator('contrastField', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '瀵规瘮瀛楁!'
+                  }
+                ]
+              })(
+                <Select
+                  showSearch
+                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                >
+                  {contFields.map(item => (
+                    <Select.Option key={item.uuid} title={item.label + '(' + item.field + ')'} value={item.field}>{item.label + '(' + item.field + ')'}</Select.Option>
+                  ))}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={6}>
+            <Form.Item label={
+              <Tooltip placement="topLeft" title="鍗$墖绫诲瀷锛屽湪鍗$墖鍥捐〃涓捣鏁�">
+                <Icon type="question-circle" />
+                {'鏍囪'}
+              </Tooltip>
+            }>
+              {getFieldDecorator('signType', {
+                initialValue: 'background',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '鏍囪鏂瑰紡!'
+                  }
+                ]
+              })(
+                <Select onChange={this.changeSignType}>
+                  <Select.Option value="font">鍗曞厓鏍硷紙鏂囧瓧锛�</Select.Option>
+                  <Select.Option value="background">鍗曞厓鏍硷紙鑳屾櫙锛�</Select.Option>
+                  <Select.Option value="line">琛�</Select.Option>
+                  <Select.Option value="icon">鍥炬爣</Select.Option>
+                  <Select.Option value="card">鍗$墖</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+          {signType === 'icon' ? <Col span={6}>
+            <Form.Item label={'鍥炬爣浣嶇疆'}>
+              {getFieldDecorator('position', {
+                initialValue: 'back'
+              })(
+                <Radio.Group>
+                  <Radio value="front">鍓�</Radio>
+                  <Radio value="back">鍚�</Radio>
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {signType === 'icon' ? <Col span={6}>
+            <Form.Item label={'鍥炬爣绫诲瀷'}>
+              {getFieldDecorator('iconType', {
+                initialValue: 'direction'
+              })(
+                <Select onChange={this.changeIconType}>
+                  <Select.Option value="direction">鏂瑰悜鎬у浘鏍�</Select.Option>
+                  <Select.Option value="hint">鎻愮ず寤鸿鎬у浘鏍�</Select.Option>
+                  <Select.Option value="edit">缂栬緫绫诲浘鏍�</Select.Option>
+                  <Select.Option value="data">鏁版嵁绫诲浘鏍�</Select.Option>
+                  <Select.Option value="trademark">鍝佺墝鍜屾爣璇�</Select.Option>
+                  <Select.Option value="normal">缃戠珯閫氱敤鍥炬爣</Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {signType === 'icon' ? <Col span={6}>
+            <Form.Item label={'鍥炬爣'}>
+              {getFieldDecorator('icon', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '鍥炬爣!'
+                  }
+                ]
+              })(
+                <Select onChange={this.changeIcon} getPopupContainer={() => document.getElementById('model-mark-form-box')}>
+                  {icons.map(icon => <Select.Option key={icon} value={icon}><Icon type={icon} /></Select.Option>)}
+                </Select>
+              )}
+            </Form.Item>
+          </Col> : null}
+          {(signType === 'icon' && selectIcon) || signType !== 'icon' ? <Col span={6}>
+            <Form.Item label="棰滆壊">
+              {getFieldDecorator('color', {
+                initialValue: '',
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.select'] + '棰滆壊!'
+                  }
+                ]
+              })(
+                <Cascader
+                  options={options}
+                  placeholder=""
+                  displayRender={(label, selectedOptions) => selectedOptions[0] ? selectedOptions[0].label + (selectedOptions[1] ? ' / ' + selectedOptions[1].value : '') : ''}
+                  getPopupContainer={() => document.getElementById('model-mark-form-box')}
+                />
+              )}
+            </Form.Item>
+          </Col> : null}
+          <Col span={signType === 'icon' ? (!selectIcon ? 24 : 18) : 12} style={{textAlign: 'right', marginBottom: 10}}>
+            <Button onClick={this.handleConfirm} type="primary" className="mk-green">
+              淇濆瓨
+            </Button>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(UniqueForm)
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.scss b/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.scss
new file mode 100644
index 0000000..4b38df3
--- /dev/null
+++ b/src/menu/components/table/normal-table/columncomponent/markcolumn/markform/index.scss
@@ -0,0 +1,7 @@
+#model-mark-form-box {
+  .ant-select-dropdown-menu-item {
+    .anticon {
+      font-size: 18px;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/table/normal-table/index.jsx b/src/menu/components/table/normal-table/index.jsx
index bf244ea..a344fde 100644
--- a/src/menu/components/table/normal-table/index.jsx
+++ b/src/menu/components/table/normal-table/index.jsx
@@ -4,7 +4,7 @@
 import { is, fromJS } from 'immutable'
 import { Icon, Popover, Modal } from 'antd'
 
-// import asyncComponent from '@/utils/asyncComponent'
+import asyncComponent from '@/utils/asyncComponent'
 import asyncIconComponent from '@/utils/asyncIconComponent'
 
 import MKEmitter from '@/utils/events.js'
@@ -12,10 +12,12 @@
 import zhCN from '@/locales/zh-CN/model.js'
 import enUS from '@/locales/en-US/model.js'
 
-import SearchComponent from '@/templates/sharecomponent/searchcomponent'
 import './index.scss'
 
 const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent'))
+const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
+const ColumnComponent = asyncComponent(() => import('./columncomponent'))
 // const WrapComponent = asyncIconComponent(() => import('../data-card/wrapsetting'))
 // const SearchComponent = asyncComponent(() => import('@/menu/searchcomponent'))
 
@@ -46,17 +48,31 @@
         parentId: card.parentId || '',
         format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
         pageable: true,     // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
-        switchable: false,  // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        switchable: true,   // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
         dataName: card.dataName || '',
-        width: 12,
-        search: [],
+        width: 24,
+        search: [
+          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'text', match: 'like' },
+          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'select', match: 'equal' },
+          { origin: true, uuid: Utils.getuuid(), label: 'label', type: 'date', match: 'greater' }
+        ],
+        action: [
+          { origin: true, uuid: Utils.getuuid(), label: '娣诲姞', intertype: 'system', OpenType: 'pop', icon: 'plus', class: 'green' },
+          { origin: true, uuid: Utils.getuuid(), label: '淇敼', intertype: 'system', OpenType: 'pop', icon: 'form', class: 'purple' },
+          { origin: true, uuid: Utils.getuuid(), label: '鍒犻櫎', intertype: 'system', OpenType: 'prompt', icon: 'delete', class: 'red' }
+        ],
         name: card.name,
         subtype: card.subtype,
         setting: { interType: 'system' },
-        wrap: { name: card.name, width: 12 },
+        wrap: { name: card.name, width: 24 },
         style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
         headerStyle: { fontSize: '16px' },
         columns: [],
+        cols: [
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 }
+        ],
         scripts: []
       }
       
@@ -171,53 +187,91 @@
   }
 
   addSearch = () => {
-    const { card } = this.state
+    let card = fromJS(this.state.card).toJS()
 
     let newcard = {}
     newcard.uuid = Utils.getuuid()
     newcard.focus = true
 
     newcard.label = 'label'
-    newcard.initval = ''
-    newcard.type = 'select'
-    newcard.resourceType = '0'
-    newcard.options = []
-    newcard.setAll = 'false'
-    newcard.orderType = 'asc'
-    newcard.display = 'dropdown'
+    newcard.type = 'text'
     newcard.match = '='
 
-    // 娉ㄥ唽浜嬩欢-娣诲姞鎼滅储
-    MKEmitter.emit('addSearch', card.uuid, newcard)
+    card.search.push(newcard)
+
+    this.setState({card})
+  }
+
+  addButton = () => {
+    const { card } = this.state
+
+    let newcard = {}
+    newcard.uuid = Utils.getuuid()
+    newcard.focus = true
+    
+    newcard.label = 'label'
+    newcard.sqlType = ''
+    newcard.Ot = 'requiredSgl'
+    newcard.OpenType = 'pop'
+    newcard.icon = ''
+    newcard.class = 'green'
+    newcard.intertype = card.setting.interType || 'system'
+    newcard.innerFunc = card.setting.innerFunc || ''
+    newcard.sysInterface = card.setting.sysInterface || ''
+    newcard.outerFunc = card.setting.outerFunc || ''
+    newcard.interface = card.setting.interface || ''
+    newcard.execSuccess = 'grid'
+    newcard.execError = 'never'
+    newcard.errorTime = 10
+    newcard.verify = null
+    newcard.show = 'button'
+
+    // 娉ㄥ唽浜嬩欢-娣诲姞鎸夐挳
+    MKEmitter.emit('addButton', card.uuid, newcard)
   }
 
   /**
    * @description 鏇存柊鎼滅储鏉′欢閰嶇疆淇℃伅
    */
-  updatesearch = (config) => {
+  updateconfig = (config) => {
     this.setState({
       card: config
     })
+    this.props.updateConfig(config)
+  }
+
+  setSubConfig = (btn) => {
+
+  }
+  updateaction = (config) => {
+
   }
 
   render() {
+    const { menu } = this.props
     const { card } = this.state
 
     return (
       <div className="menu-normal-table-edit-box" style={{...card.style, height: card.wrap.height}}>
-        <SearchComponent config={card} updatesearch={this.updatesearch}/>
         <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
           <div className="mk-popover-control">
-            <Icon className="plus" title="娣诲姞鍗$墖" onClick={this.addCard} type="plus" />
-            <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" />
+            {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch} type="plus-circle" /> : null}
+            {menu && menu.MenuType !== 'billPrint' ? <Icon className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton} type="plus-square" /> : null}
             {/* {menu ? <WrapComponent config={card} MenuType={menu.MenuType} updateConfig={this.updateComponent} /> : null} */}
             <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
             <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
-            {card.wrap.datatype !== 'static' ? <SettingComponent config={card} updateConfig={this.updateComponent} /> : null}
+            <SettingComponent config={card} updateConfig={this.updateComponent} />
           </div>
         } trigger="hover">
           <Icon type="tool" />
         </Popover>
+        <SearchComponent config={card} updatesearch={this.updateconfig}/>
+        <ActionComponent
+          type="normaltable"
+          config={card}
+          updateaction={this.updateComponent}
+        />
+        <ColumnComponent config={card} updatecolumn={this.updateconfig}/>
       </div>
     )
   }
diff --git a/src/menu/components/table/normal-table/index.scss b/src/menu/components/table/normal-table/index.scss
index 6ca24a0..0077e7e 100644
--- a/src/menu/components/table/normal-table/index.scss
+++ b/src/menu/components/table/normal-table/index.scss
@@ -7,32 +7,18 @@
   background-size: cover;
   min-height: 100px;
   
-  .table-header {
-    position: relative;
-    height: 45px;
-    overflow: hidden;
-    padding-right: 35px;
-
-    .table-title {
-      text-decoration: inherit;
-      font-weight: inherit;
-      font-style: inherit;
-      float: left;
-      line-height: 45px;
-      margin-left: 10px;
-      position: relative;
-      z-index: 1;
+  .model-table-search-list {
+    padding: 10px 0px 0px;
+    min-height: 65px;
+    >.anticon-question-circle {
+      display: none;
+    }
+    .page-card {
+      background: transparent;
     }
   }
-  .card-control {
-    position: absolute;
-    top: 0px;
-    left: 0px;
-    .anticon-tool {
-      right: auto;
-      left: 1px;
-      padding: 1px;
-    }
+  .model-table-search-list.length0 {
+    display: none;
   }
   .anticon-tool {
     position: absolute;
@@ -44,32 +30,12 @@
     padding: 5px;
     background: rgba(255, 255, 255, 0.55);
   }
-
-  .card-item {
-    overflow-y: hidden;
-    position: relative;
-    background-position: center center;
-    background-repeat: no-repeat;
-    background-size: cover;
-    min-height: 20px;
-  }
-  
-  .card-item:hover {
-    box-shadow: 0px 0px 2px #e8e8e8;
-  }
-
-  .model-menu-card-cell-list .card-detail-row > .anticon-plus {
-    position: absolute;
-    right: -30px;
-    font-size: 16px;
-  }
   .model-menu-action-list {
     line-height: 40px;
-    .ant-row > .anticon-plus {
-      position: absolute;
-      right: -30px;
-      font-size: 16px;
-    }
+    padding: 15px 0px 10px;
+  }
+  .model-menu-action-list.length0 {
+    display: none;
   }
   .card-add-button {
     text-align: right;
diff --git a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
index 70cbff2..23f1f6a 100644
--- a/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-bar-line/index.jsx
@@ -2,6 +2,7 @@
 import PropTypes from 'prop-types'
 import { is, fromJS } from 'immutable'
 import { Chart } from '@antv/g2'
+import { connect } from 'react-redux'
 import DataSet from '@antv/data-set'
 import { Spin, Empty, Select, notification } from 'antd'
 
@@ -11,6 +12,7 @@
 import Api from '@/api'
 import Utils from '@/utils/utils.js'
 import UtilsDM from '@/utils/utils-datamanage.js'
+import { modifyTabview } from '@/store/action'
 import './index.scss'
 
 const ExcelOutButton = asyncComponent(() => import('@/tabviews/zshare/actionList/exceloutbutton'))
@@ -1157,6 +1159,55 @@
       }
     }
 
+    if (plot.linkmenu && plot.linkmenu.length > 0) {
+      let menu_id = plot.linkmenu[plot.linkmenu.length - 1]
+      let menu = this.props.permMenus.filter(m => m.MenuID === menu_id)[0] || ''
+
+      chart.on('element:dblclick', (ev) => {
+        if (!menu) {
+          notification.warning({
+            top: 92,
+            message: '鑿滃崟宸插垹闄ゆ垨娌℃湁璁块棶鏉冮檺锛�',
+            duration: 5
+          })
+          return
+        }
+
+        try {
+          let data = ev.data.data
+          let primaryId = ''
+          if (this.state.config.setting.primaryKey && data) {
+            primaryId = data[this.state.config.setting.primaryKey] || ''
+          }
+
+          let newtab = {
+            ...menu,
+            selected: true,
+            param: {
+              BID: primaryId,
+              data: data
+            }
+          }
+  
+          let tabs = this.props.tabviews.filter(tab => {
+            tab.selected = false
+            return tab.MenuID !== newtab.MenuID
+          })
+  
+          if (this.props.tabviews.length !== tabs.length) {
+            this.props.modifyTabview(fromJS(tabs).toJS())
+          }
+  
+          this.setState({}, () => {
+            tabs.push(newtab)
+            this.props.modifyTabview(tabs)
+          })
+        } catch {
+          console.warn('鑿滃崟鎵撳紑澶辫触锛�')
+        }
+      })
+    }
+
     chart.render()
   }
 
@@ -1237,4 +1288,17 @@
   }
 }
 
-export default LineChart
\ No newline at end of file
+const mapStateToProps = (state) => {
+  return {
+    tabviews: state.tabviews,
+    permMenus: state.permMenus,
+  }
+}
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    modifyTabview: (tabviews) => dispatch(modifyTabview(tabviews))
+  }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(LineChart)
\ No newline at end of file
diff --git a/src/tabviews/custom/components/chart/antv-pie/index.jsx b/src/tabviews/custom/components/chart/antv-pie/index.jsx
index 2cedfda..dd7fa3f 100644
--- a/src/tabviews/custom/components/chart/antv-pie/index.jsx
+++ b/src/tabviews/custom/components/chart/antv-pie/index.jsx
@@ -551,7 +551,6 @@
   }
 }
 
-
 const mapStateToProps = (state) => {
   return {
     tabviews: state.tabviews,
diff --git a/src/tabviews/custom/components/share/tabtransfer/index.jsx b/src/tabviews/custom/components/share/tabtransfer/index.jsx
index a10e6ee..fd9c277 100644
--- a/src/tabviews/custom/components/share/tabtransfer/index.jsx
+++ b/src/tabviews/custom/components/share/tabtransfer/index.jsx
@@ -179,7 +179,7 @@
     const { config } = this.props
     let LText_field = []
     let diffUser = false
-    let LText = params.map((item, index) => {
+    let _LText = params.map((item, index) => {
       let _script = item.script
 
       if (index === 0) {
@@ -199,11 +199,15 @@
 
     let param = {
       func: 'sPC_Get_structured_data',
-      LText: LText.join(' union all '),
+      LText: _LText.join(' union all '),
       LText_field: LText_field.join(' union all ')
     }
 
-    param.LText = Utils.formatOptions(param.LText)
+    let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
+
+    param.LText1 = LText1
+    param.LText = LText
+    param.LText2 = LText2
     param.LText_field = Utils.formatOptions(param.LText_field)
 
     if (config.cacheUseful === 'true') {
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index bd7a621..e9ac035 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -374,7 +374,7 @@
     const { config } = this.state
     let LText_field = []
     let diffUser = false
-    let LText = params.map((item, index) => {
+    let _LText = params.map((item, index) => {
       let _script = item.script
 
       if (index === 0) {
@@ -392,14 +392,19 @@
       return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(item.sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
     })
 
+    // 鎶婂ぇ鎺ュ彛sPC_Get_structured_data鐨刲text鎷嗘垚涓変唤锛岀涓�娈碉細@LText1锛岀浜屾@LText锛岀涓夋@LText2
     let param = {
       func: 'sPC_Get_structured_data',
-      LText: LText.join(' union all '),
+      LText: _LText.join(' union all '),
       LText_field: LText_field.join(' union all '),
       BID: this.state.BID || ''
     }
 
-    param.LText = Utils.formatOptions(param.LText)
+    let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(param.LText)
+
+    param.LText1 = LText1
+    param.LText = LText
+    param.LText2 = LText2
     param.LText_field = Utils.formatOptions(param.LText_field)
 
     if (config.cacheUseful === 'true') {
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
index 0c0ee33..4c2c87e 100644
--- a/src/templates/comtableconfig/source.jsx
+++ b/src/templates/comtableconfig/source.jsx
@@ -74,8 +74,7 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'add',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'notRequired',
         position: 'toolbar',
         execSuccess: 'grid',
@@ -89,10 +88,9 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'update',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'requiredSgl',
-        position: 'grid',
+        position: 'toolbar',
         execSuccess: 'grid',
         execError: 'never',
         errorTime: 15,
@@ -104,8 +102,7 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'delete',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'required',
         position: 'toolbar',
         execSuccess: 'grid',
diff --git a/src/templates/formtabconfig/dragelement/index.jsx b/src/templates/formtabconfig/dragelement/index.jsx
index caf0924..9776ef4 100644
--- a/src/templates/formtabconfig/dragelement/index.jsx
+++ b/src/templates/formtabconfig/dragelement/index.jsx
@@ -127,7 +127,6 @@
         newcard.linkTab = ''
         newcard.class = 'default'
         newcard.intertype = 'inner'
-        newcard.method = 'POST'
         newcard.position = 'toolbar'
         newcard.execSuccess = 'grid'
         newcard.execError = 'never'
diff --git a/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
index 4fbfca7..9d610bd 100644
--- a/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/dragaction/index.jsx
@@ -106,7 +106,6 @@
       newcard.icon = ''
       newcard.class = 'default'
       newcard.intertype = 'system'
-      newcard.method = 'POST'
       newcard.position = 'toolbar'
       newcard.execSuccess = 'grid'
       newcard.execError = 'never'
diff --git a/src/templates/sharecomponent/actioncomponent/index.jsx b/src/templates/sharecomponent/actioncomponent/index.jsx
index c7ccd61..7b6ec62 100644
--- a/src/templates/sharecomponent/actioncomponent/index.jsx
+++ b/src/templates/sharecomponent/actioncomponent/index.jsx
@@ -62,7 +62,7 @@
     if (!is(fromJS(nextProps.config.action), fromJS(this.props.config.action)) && !is(fromJS(nextProps.config.action), fromJS(actionlist))) {
       let len = nextProps.config.action.length
       let item = nextProps.config.action[len - 1]
-      if (item.copyType && item.focus) {
+      if (item && item.focus) {
         this.handleAction(item)
       }
       this.setState({actionlist: fromJS(nextProps.config.action).toJS()})
diff --git a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
index 9c3a55b..4af02e9 100644
--- a/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/dragsearch/index.jsx
@@ -2,7 +2,7 @@
 import { useDrop } from 'react-dnd'
 import { is, fromJS } from 'immutable'
 import update from 'immutability-helper'
-import { Col } from 'antd'
+import { Col, Button } from 'antd'
 import Utils from '@/utils/utils.js'
 import Card from './card'
 import './index.scss'
@@ -138,7 +138,17 @@
           />
         </Col>
       ))}
-      
+      {cards.length > 0 ? <Col key="action" className="action" span={6}>
+        <div className="ant-row ant-form-item" style={{lineHeight: '40px', height: '55px', marginBottom: 0}}>
+          <div className="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-8">
+          </div>
+          <div className="ant-col ant-form-item-control-wrapper ant-col-xs-24 ant-col-sm-16">
+            <Button type="primary">鎼滅储</Button>
+            <Button style={{ marginLeft: 8 }}>閲嶇疆</Button>
+            <div style={{position: 'absolute', top: 0, bottom: 0, left: 0, right: 0}}></div>
+          </div>
+        </div>
+      </Col> : null}
       {cards.length === 0 ?
         <div className="common-drawarea-placeholder">
           {placeholder}
diff --git a/src/templates/sharecomponent/searchcomponent/index.jsx b/src/templates/sharecomponent/searchcomponent/index.jsx
index 73306fc..fbaf4e2 100644
--- a/src/templates/sharecomponent/searchcomponent/index.jsx
+++ b/src/templates/sharecomponent/searchcomponent/index.jsx
@@ -48,7 +48,7 @@
     if (!is(fromJS(nextProps.config.search), fromJS(this.props.config.search)) && !is(fromJS(nextProps.config.search), fromJS(searchlist))) {
       let len = nextProps.config.search.length
       let item = nextProps.config.search[len - 1]
-      if (item.copyType && item.focus) {
+      if (item && item.focus) {
         this.handleSearch(item)
       }
       this.setState({searchlist: fromJS(nextProps.config.search).toJS()})
@@ -277,7 +277,7 @@
     const { dict, searchlist, visible, sqlVerifing, card } = this.state
 
     return (
-      <div className="model-table-search-list">
+      <div className={'model-table-search-list length' + searchlist.length}>
         <Tooltip placement="bottomLeft" overlayClassName="middle" title={dict['model.tooltip.search.guide']}>
           <Icon type="question-circle" />
         </Tooltip>
diff --git a/src/templates/subtableconfig/source.jsx b/src/templates/subtableconfig/source.jsx
index e71cdb6..d58938e 100644
--- a/src/templates/subtableconfig/source.jsx
+++ b/src/templates/subtableconfig/source.jsx
@@ -73,8 +73,7 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'add',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'notRequired',
         position: 'toolbar',
         execSuccess: 'grid',
@@ -88,8 +87,7 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'update',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'requiredSgl',
         position: 'grid',
         execSuccess: 'grid',
@@ -103,8 +101,7 @@
         origin: true,
         uuid: Utils.getuuid(),
         label: 'delete',
-        intertype: 'inner',
-        method: 'POST',
+        intertype: 'system',
         Ot: 'required',
         position: 'toolbar',
         execSuccess: 'grid',
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 76f7af3..a2b1ad5 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -252,11 +252,21 @@
       return window.btoa(_value)
     }
 
+    let len = value.length
     // 娉細LText 涓� LText1 椤哄簭棰犲��
-    return {
-      LText: encodesql(value.substring(5000, 10000)),
-      LText1: encodesql(value.substring(0, 5000)),
-      LText2: encodesql(value.substring(10000))
+    if (len > 1000) {
+      let limit = Math.floor(len / 3)
+      return {
+        LText1: encodesql(value.substring(0, limit)),
+        LText: encodesql(value.substring(limit, limit * 2)),
+        LText2: encodesql(value.substring(limit * 2))
+      }
+    } else {
+      return {
+        LText1: '',
+        LText: encodesql(value),
+        LText2: ''
+      }
     }
   }
 
diff --git a/src/views/menudesign/index.jsx b/src/views/menudesign/index.jsx
index 49ff781..4d27f54 100644
--- a/src/views/menudesign/index.jsx
+++ b/src/views/menudesign/index.jsx
@@ -97,7 +97,6 @@
     }
 
     let _config = fromJS(config).toJS()
-    delete _config.fstMenuList
     delete _config.tableFields
 
     if (!is(fromJS(oriConfig), fromJS(_config))) {
@@ -262,7 +261,6 @@
     }
 
     let _config = fromJS(config).toJS()
-    delete _config.fstMenuList
     delete _config.tableFields
 
     let param = {
@@ -418,13 +416,6 @@
     })
   }
 
-  initMenuList = (msg) => {
-    let config = {...this.state.config, ...msg}
-
-    this.setState({config})
-    this.props.modifyCustomMenu(config)
-  }
-
   onEnabledChange = () => {
     const { config } = this.state
 
@@ -518,7 +509,6 @@
                       parentId={ParentId}
                       MenuName={MenuName}
                       MenuNo={MenuNo}
-                      initMenuList={this.initMenuList}
                       updateConfig={this.updateConfig}
                     /> : null}
                     {config && MenuType === 'home' ? <HomeForm
diff --git a/src/views/menudesign/menuform/index.jsx b/src/views/menudesign/menuform/index.jsx
index a1d10bf..b9a5833 100644
--- a/src/views/menudesign/menuform/index.jsx
+++ b/src/views/menudesign/menuform/index.jsx
@@ -1,6 +1,5 @@
 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
-import { fromJS } from 'immutable'
 import { Form, Row, Col, Input, Select, notification, Radio, Icon, Tooltip, InputNumber } from 'antd'
 
 import Api from '@/api'
@@ -15,7 +14,6 @@
     MenuName: PropTypes.string,
     MenuNo: PropTypes.string,
     parentId: PropTypes.string,
-    initMenuList: PropTypes.func,
     updateConfig: PropTypes.func
   }
 
@@ -26,7 +24,7 @@
   }
 
   UNSAFE_componentWillMount () {
-    const { MenuId } = this.props
+    const { MenuId, config } = this.props
     let _param = {func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'}
     if (options.sysType !== 'cloud' && window.GLOB.systemType !== 'production') {
       _param.linkurl = window.GLOB.linkurl
@@ -89,8 +87,8 @@
             smenulist = item.children
           }
         })
-
-        this.props.initMenuList({fstMenuList: fromJS(menulist).toJS(), fstMenuId: thdMenu ? thdMenu.FstId : ''})
+        sessionStorage.setItem('fstMenuList', JSON.stringify(menulist))
+        this.props.updateConfig({...config, fstMenuId: thdMenu ? thdMenu.FstId : ''})
 
         this.setState({
           fstMenuId: thdMenu ? thdMenu.FstId : '',
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index ce401ef..92dbcf0 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -192,77 +192,6 @@
     })
   }
 
-  testFunc = () => {
-    let datas = [{
-      name: 'a',
-      arr_field: 'MapCode,Country',
-      par_tablename: '',
-      type: '',
-      primaryKey: 'MapCode',
-      foreign_key: '',
-      sql: `select MapCode,Country from @tc1`,
-      script: `declare @tc1 table (MapCode nvarchar(50),Country nvarchar(50)) insert into @tc1 (MapCode,Country) select MapCode,Country from sMap where Province=''`
-    }, {
-      name: 'b',
-      arr_field: 'MapCode,Province,ParMapCode',
-      par_tablename: 'a',
-      type: 'array',
-      primaryKey: 'MapCode',
-      foreign_key: 'ParMapCode',
-      sql: `select MapCode,Province,ParMapCode from @tc2`,
-      script: `declare @tc2 table (MapCode nvarchar(50),Province nvarchar(50),ParMapCode nvarchar(50)) insert into @tc2 (MapCode,Province,ParMapCode) select MapCode,Province,ParMapCode from sMap where Province!='' and City=''`
-    }, {
-      name: 'c',
-      arr_field: 'MapCode,City,ParMapCode',
-      par_tablename: 'b',
-      type: 'array',
-      primaryKey: 'MapCode',
-      foreign_key: 'ParMapCode',
-      sql: `select MapCode,City,ParMapCode from @tc3`,
-      script: `declare @tc3 table (MapCode nvarchar(50),City nvarchar(50),ParMapCode nvarchar(50)) insert into @tc3 (MapCode,City,ParMapCode) select MapCode,City,ParMapCode from sMap where City!='' and Area=''`
-    }, {
-      name: 'd',
-      arr_field: 'MapCode,Area,ParMapCode',
-      par_tablename: 'c',
-      type: 'array',
-      primaryKey: 'MapCode',
-      foreign_key: 'ParMapCode',
-      sql: `select MapCode,Area,ParMapCode from sMap where Area!=''`,
-      script: ``
-    }]
-
-    let LText = datas.map((item, index) => {
-      // item.par_tablename = ''
-      // item.foreign_key = ''
-
-      let _orderBy = 'MapCode desc'
-      let _search = ''
-      let _sql = `select top 1000 ${item.arr_field} from (select ${item.arr_field} ,ROW_NUMBER() over(order by ${_orderBy}) as rows from (${item.sql}) tb ${_search}) tmptable order by tmptable.rows `
-      
-      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(item.script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
-    })
-    
-    let LText_field = []
-    datas.forEach(item => {
-      item.arr_field.split(',').forEach(cell => {
-        LText_field.push(`Select '${item.name}' as tablename,'${cell}' as fieldname,'nvarchar(50)' as field_type`)
-      })
-    })
-    
-    let param = {
-      func: 'sPC_Get_structured_data',
-      LText: LText.join(' union all '),
-      LText_field: LText_field.join(' union all ')
-    }
-
-    param.LText = Utils.formatOptions(param.LText)
-    param.LText_field = Utils.formatOptions(param.LText_field)
-    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
-    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
-
-    Api.getLocalConfig(param)
-  }
-
   // save = () => {
   //   html2canvas(document.getElementById('view')).then(canvas => {
   //     let imgUri = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream'); // 鑾峰彇鐢熸垚鐨勫浘鐗囩殑url

--
Gitblit v1.8.0