From 665b7b5866f726030ec0335834c2ba80060c86e8 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 26 八月 2022 11:08:40 +0800
Subject: [PATCH] 2022-08-26

---
 src/menu/tableshell/index.scss                                         |   21 
 src/templates/formtabconfig/index.jsx                                  |  311 -----
 src/mob/searchconfig/index.scss                                        |   58 
 src/menu/components/table/base-table/columns/editColumn/formconfig.jsx |  424 ++++++
 public/options.json                                                    |    2 
 src/views/tabledesign/index.jsx                                        |   49 
 src/views/tabledesign/menuform/index.jsx                               |   14 
 src/menu/components/table/base-table/index.scss                        |   92 +
 src/templates/sharecomponent/tablecomponent/index.jsx                  |   10 
 src/views/mobdesign/index.scss                                         |   32 
 src/views/pcdesign/index.scss                                          |   30 
 src/views/imdesign/index.scss                                          |   30 
 src/menu/tableshell/card.jsx                                           |   56 
 src/mob/modalconfig/index.scss                                         |   35 
 src/templates/treepageconfig/index.scss                                |   32 
 src/views/tabledesign/index.scss                                       |   37 
 src/templates/formtabconfig/index.scss                                 |   35 
 src/menu/components/table/base-table/columns/index.scss                |  146 ++
 src/menu/components/table/base-table/columns/editColumn/index.jsx      |  398 ++++++
 src/templates/calendarconfig/index.scss                                |   31 
 src/templates/modalconfig/index.scss                                   |   35 
 src/menu/tableshell/index.jsx                                          |  132 ++
 src/views/popdesign/index.scss                                         |   30 
 src/menu/components/table/base-table/options.jsx                       |  274 ++++
 src/templates/sharecomponent/tablecomponent/index.scss                 |   28 
 src/templates/subtableconfig/index.scss                                |   31 
 src/templates/comtableconfig/index.scss                                |   31 
 src/menu/modalconfig/index.scss                                        |   35 
 src/menu/components/table/base-table/columns/index.jsx                 |  618 ++++++++++
 src/views/menudesign/index.scss                                        |   30 
 src/menu/components/table/base-table/columns/editColumn/index.scss     |   17 
 src/menu/components/table/base-table/index.jsx                         |  554 +++++++++
 32 files changed, 2,820 insertions(+), 838 deletions(-)

diff --git a/public/options.json b/public/options.json
index 523da64..79f67c8 100644
--- a/public/options.json
+++ b/public/options.json
@@ -8,7 +8,7 @@
   "filter": "false",
   "defaultApp": "mk",
   "defaultLang": "zh-CN",
-  "WXAppID": "",
+  "WXAppID": "wx4d8a34c8d4494872",
   "WXminiAppID": "",
   "debugger": false,
   "licenseKey": "",
diff --git a/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
new file mode 100644
index 0000000..8ff4f0d
--- /dev/null
+++ b/src/menu/components/table/base-table/columns/editColumn/formconfig.jsx
@@ -0,0 +1,424 @@
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+
+const Formdict = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
+
+/**
+ * @description 鑾峰彇鏄剧ず鍒楄〃鍗曢厤缃俊鎭�
+ * @param {object} card       // 鎼滅储鏉′欢瀵硅薄
+ */
+export function getColumnForm (card, fields = []) {
+  let appType = sessionStorage.getItem('appType')
+  let roleList = sessionStorage.getItem('sysRoles')
+  if (roleList) {
+    try {
+      roleList = JSON.parse(roleList)
+    } catch (e) {
+      roleList = []
+    }
+  } else {
+    roleList = []
+  }
+
+  let menulist = []
+
+  if (appType === 'pc') {
+    menulist = sessionStorage.getItem('appMenus')
+  } else if (!appType) {
+    menulist = sessionStorage.getItem('fstMenuList')
+  }
+
+  if (menulist) {
+    try {
+      menulist = JSON.parse(menulist)
+    } catch (e) {
+      menulist = []
+    }
+  } else {
+    menulist = []
+  }
+
+  let options = [{
+    value: 'text',
+    text: Formdict['model.form.text']
+  }, {
+    value: 'number',
+    text: Formdict['model.form.number']
+  }, {
+    value: 'picture',
+    text: Formdict['model.form.picture']
+  }, {
+    value: 'link',
+    text: Formdict['model.form.href']
+  }, {
+    value: 'textarea',
+    text: Formdict['model.form.textarea']
+  }, {
+    value: 'custom',
+    text: '鑷畾涔夊垪'
+  }, {
+    value: 'colspan',
+    text: '鍚堝苟鍒�'
+  }, {
+    value: 'formula',
+    text: '鍏紡'
+  }, {
+    value: 'index',
+    text: '搴忓彿'
+  }]
+
+  if (!card.isSub) {
+    options.push({
+      value: 'action',
+      text: '鎿嶄綔'
+    })
+  }
+
+  if (!card.linkurl && (!card.linkmenu || card.linkmenu.length === 0)) {
+    card.perspective = ''
+  }
+
+  return [
+    {
+      type: 'text',
+      key: 'label',
+      label: '鍒楀ご鏂囧瓧',
+      initVal: card.label,
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'type',
+      label: Formdict['model.form.type'],
+      initVal: card.type,
+      required: true,
+      options: options
+    },
+    {
+      type: 'select',
+      key: 'field',
+      label: Formdict['model.form.field'],
+      initVal: card.field,
+      required: true,
+      options: fields
+    },
+    {
+      type: 'select',
+      key: 'nameField',
+      label: Formdict['model.name'] + Formdict['model.form.field'],
+      initVal: card.nameField || '',
+      required: false,
+      options: [{uuid: 'empty', field: '', label: '绌�'}, ...fields]
+    },
+    {
+      type: 'number',
+      key: 'Width',
+      min: 20,
+      max: 1000,
+      decimal: 0,
+      label: Formdict['model.form.columnWidth'],
+      initVal: card.Width || 120,
+      required: true
+    },
+    {
+      type: 'radio',
+      key: 'joint',
+      label: Formdict['model.form.paramJoint'],
+      initVal: card.joint || 'true',
+      required: true,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'Hide',
+      label: Formdict['model.hidden'],
+      initVal: card.Hide || 'false',
+      required: true,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'IsSort',
+      label: Formdict['model.sort'],
+      initVal: card.IsSort || (card.isSub ? 'false' : 'true'),
+      required: true,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'Align',
+      label: Formdict['model.form.align'],
+      initVal: card.Align || 'left',
+      required: true,
+      options: [{
+        value: 'left',
+        text: Formdict['model.form.alignLeft']
+      }, {
+        value: 'center',
+        text: Formdict['model.form.alignCenter']
+      }, {
+        value: 'right',
+        text: Formdict['model.form.alignRight']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'rowspan',
+      label: '琛屽悎骞�',
+      initVal: card.rowspan || 'false',
+      tooltip: '鐩搁偦琛屼俊鎭浉鍚屾椂锛屽崟鍏冩牸鍚堝苟銆�',
+      required: false,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'sum',
+      label: '鏄剧ず鍚堣',
+      initVal: card.sum || 'false',
+      tooltip: '鍚堣淇℃伅鍙湪浣跨敤绯荤粺鏁版嵁婧愭椂鏈夋晥銆�',
+      required: false,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'number',
+      key: 'decimal',
+      min: 0,
+      max: 18,
+      decimal: 0,
+      label: Formdict['header.form.decimal'],
+      initVal: card.decimal || 0,
+      required: true
+    },
+    {
+      type: 'select',
+      key: 'format',
+      label: Formdict['header.form.format'],
+      initVal: card.format || 'none',
+      options: [{
+        value: 'none',
+        text: '鏃�'
+      }, {
+        value: 'thdSeparator',
+        text: '鍗冨垎浣�'
+      }, {
+        value: 'percent',
+        text: '鐧惧垎姣�'
+      }, {
+        value: 'abs',
+        text: '缁濆鍊�'
+      }],
+      required: false
+    },
+    {
+      type: 'select',
+      key: 'textFormat',
+      label: Formdict['header.form.format'],
+      initVal: card.textFormat || 'none',
+      options: [{
+        value: 'none',
+        text: '鏃�'
+      }, {
+        value: 'encryption',
+        text: '鍔犲瘑'
+      }, {
+        value: 'YYYY-MM-DD',
+        text: 'YYYY-MM-DD'
+      }, {
+        value: 'YYYY-MM-DD HH:mm:ss',
+        text: 'YYYY-MM-DD HH:mm:ss'
+      }],
+      required: false
+    },
+    {
+      type: 'text',
+      key: 'prefix',
+      label: Formdict['header.form.prefix'],
+      initVal: card.prefix || '',
+      required: false,
+      readonly: false
+    },
+    {
+      type: 'text',
+      key: 'postfix',
+      label: Formdict['header.form.postfix'],
+      initVal: card.postfix || '',
+      required: false,
+      readonly: false
+    },
+    {
+      type: 'select',
+      key: 'lenWidRadio',
+      label: '闀垮姣�',
+      initVal: card.lenWidRadio || '1:1',
+      required: true,
+      options: [
+        { value: '1:1', text: '1:1' },
+        { value: '4:3', text: '4:3' },
+        { value: '3:2', text: '3:2' },
+        { value: '16:9', text: '16:9' },
+        { value: '2:1', text: '2:1' },
+        { value: '3:1', text: '3:1' },
+        { value: '4:1', text: '4:1' },
+        { value: '5:1', text: '5:1' },
+        { value: '6:1', text: '6:1' },
+        { value: '7:1', text: '7:1' },
+        { value: '8:1', text: '8:1' },
+        { value: '9:1', text: '9:1' },
+        { value: '10:1', text: '10:1' },
+        { value: '3:4', text: '3:4' },
+        { value: '2:3', text: '2:3' },
+        { value: '9:16', text: '9:16' },
+      ]
+    },
+    {
+      type: 'radio',
+      key: 'picSort',
+      label: '鍥剧墖鎺掑垪',
+      initVal: card.picSort || '1',
+      tooltip: '鍚屼竴鍗曞厓鏍煎唴锛屽惈鏈夊寮犲浘鐗囨椂鐨勫垪鏁般��',
+      required: false,
+      options: [{
+        value: '1',
+        text: '1'
+      }, {
+        value: '2',
+        text: '2'
+      }, {
+        value: '3',
+        text: '3'
+      }, {
+        value: '4',
+        text: '4'
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'scale',
+      label: '鐐瑰嚮缂╂斁',
+      initVal: card.scale || 'true',
+      required: false,
+      options: [{
+        value: 'true',
+        text: Formdict['model.true']
+      }, {
+        value: 'false',
+        text: Formdict['model.false']
+      }]
+    },
+    {
+      type: 'radio',
+      key: 'perspective',
+      label: '瀛楁閫忚',
+      initVal: card.perspective || '',
+      options: [{
+        value: '',
+        text: '鏃�'
+      }, {
+        value: 'linkmenu',
+        text: '鑿滃崟'
+      }, {
+        value: 'linkurl',
+        text: '閾炬帴'
+      }],
+      forbidden: appType === 'mob'
+    },
+    {
+      type: appType === 'pc' ? 'select' : 'cascader',
+      key: 'linkmenu',
+      label: Formdict['model.menu'],
+      initVal: card.linkmenu || (appType === 'pc' ? '' : []),
+      required: true,
+      options: menulist,
+      forbidden: appType === 'mob'
+    },
+    {
+      type: 'textarea',
+      key: 'linkurl',
+      label: '閾炬帴鍦板潃',
+      initVal: card.linkurl || '',
+      required: true,
+      forbidden: appType === 'mob'
+    },
+    {
+      type: 'multiselect',
+      key: 'linkfields',
+      label: '鍏宠仈瀛楁',
+      initVal: card.linkfields || [],
+      required: false,
+      options: fields,
+      forbidden: appType === 'mob'
+    },
+    {
+      type: 'radio',
+      key: 'open',
+      label: '鎵撳紑鏂瑰紡',
+      initVal: card.open || 'blank',
+      required: false,
+      forbid: appType !== 'pc',
+      options: [
+        { value: 'blank', text: '鏂扮獥鍙�' },
+        { value: 'self', text: '褰撳墠绐楀彛' }
+      ]
+    },
+    {
+      type: 'radio',
+      key: 'eval',
+      label: '瑙f瀽',
+      initVal: card.eval || 'true',
+      tooltip: '褰撳叕寮忓唴瀹规秹鍙婅绠楁椂璇烽�夋嫨鈥滄槸鈥濓紝褰撳叕寮忓唴瀹逛负瀛楁鎷兼帴鏃惰閫夋嫨鈥滃惁鈥濄��',
+      required: false,
+      options: [
+        { value: 'true', text: '鏄�' },
+        { value: 'false', text: '鍚�' }
+      ]
+    },
+    {
+      type: 'textarea',
+      key: 'formula',
+      label: '鍏紡',
+      initVal: card.formula || '',
+      tooltip: '鎵ц鏃朵細浣跨敤鏌ヨ鍒扮殑鏁版嵁鏇挎崲鐩稿簲鐨勫瓧娈碉紝灞曠ず鑾峰緱鐨勭粨鏋滐紝鍦ㄤ笉浣跨敤瑙f瀽鏃舵崲琛岀鎴栫┖鏍间細鏇挎崲涓洪〉闈㈠厓绱犮�傚彲浣跨敤JS鐨勪竴浜涜娉曪紝濡傦細涓夊厓琛ㄨ揪寮� @field1@ > @field2@ ? 0 : 1锛汳ath瀵硅薄锛屽彇缁濆鍊� Math.abs(@field@)銆佸洓鑸嶄簲鍏� Math.round(@field@)绛�',
+      placeholder: '渚嬪锛欯price@ * @number@',
+      required: true
+    },
+    {
+      type: 'multiselect',
+      key: 'blacklist',
+      label: Formdict['header.form.blacklist'],
+      initVal: card.blacklist || [],
+      required: false,
+      options: roleList,
+      forbidden: appType === 'mob'
+    }
+  ]
+}
diff --git a/src/menu/components/table/base-table/columns/editColumn/index.jsx b/src/menu/components/table/base-table/columns/editColumn/index.jsx
new file mode 100644
index 0000000..5a41606
--- /dev/null
+++ b/src/menu/components/table/base-table/columns/editColumn/index.jsx
@@ -0,0 +1,398 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Form, Row, Col, Input, Select, InputNumber, Radio, Tooltip, Cascader, Modal } from 'antd'
+import { QuestionCircleOutlined } from '@ant-design/icons'
+
+import { getColumnForm } from './formconfig'
+import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+const { TextArea } = Input
+const columnTypeOptions = {
+  text: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'textFormat', 'blacklist', 'perspective', 'rowspan'],
+  number: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'decimal', 'format', 'prefix', 'postfix', 'blacklist', 'perspective', 'sum', 'rowspan'],
+  link: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'joint', 'Width', 'blacklist', 'nameField'],
+  textarea: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'prefix', 'postfix', 'blacklist'],
+  picture: ['label', 'field', 'type', 'Align', 'Hide', 'IsSort', 'Width', 'blacklist', 'scale', 'lenWidRadio', 'picSort'],
+  colspan: ['label', 'type', 'Align', 'Hide', 'blacklist'],
+  custom: ['label', 'type', 'Align', 'Hide', 'Width', 'blacklist'],
+  action: ['label', 'type', 'Align', 'Width'],
+  formula: ['label', 'type', 'Align', 'Hide', 'Width', 'prefix', 'postfix', 'eval', 'formula', 'blacklist'],
+  index: ['label', 'type', 'Align', 'Width']
+}
+
+class NormalTableColumn extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,     // 瀛楀吀椤�
+    visible: PropTypes.bool,
+    column: PropTypes.object,
+    fields: PropTypes.array,
+    submitCol: PropTypes.func,  // 鎻愪氦浜嬩欢
+    cancelCol: PropTypes.func   // 鍙栨秷鏃跺垹闄や簨浠�
+  }
+
+  state = {
+    visible: false,
+    formlist: null
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (nextProps.column && !is(fromJS(this.props.column), fromJS(nextProps.column))) {
+      this.editColumn(nextProps.column)
+    }
+  }
+
+  editColumn = (column) => {
+    let fields = fromJS(this.props.fields).toJS().map(item => {
+      if (item.label.toLowerCase() !== item.field.toLowerCase()) {
+        item.text = item.label + '锛�' + item.field + '锛�'
+      }
+      return item
+    })
+    
+    let formlist = getColumnForm(column, fields)
+    let _options = fromJS(columnTypeOptions[column.type]).toJS()
+    if (column.type === 'text' || column.type === 'number') {
+      if (column.perspective === 'linkmenu') {
+        _options.push('linkmenu', 'linkfields', 'open')
+      } else if (column.perspective === 'linkurl') {
+        _options.push('linkurl', 'linkfields', 'open')
+      }
+    }
+
+    this.setState({
+      visible: true,
+      type: column.type,
+      formlist: formlist.map(item => {
+        item.hidden = !_options.includes(item.key)
+
+        return item
+      })
+    })
+    if (column.focus) {
+      setTimeout(() => {
+        try {
+          let _form = document.getElementById('label')
+          _form && _form.select()
+        } catch (e) {
+          console.warn('琛ㄥ崟focus澶辫触锛�')
+        }
+      }, 200)
+    }
+  }
+
+  typeChange = (key, value, option) => {
+    if (key === 'type') {
+      let _options = fromJS(columnTypeOptions[value]).toJS()
+
+      this.setState({
+        type: value,
+        formlist: this.state.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+
+          return item
+        })
+      }, () => {
+        if (value === 'link' || value === 'textarea' || value === 'picture') {
+          this.props.form.setFieldsValue({IsSort: 'false'})
+        } else if (value === 'text' || value === 'number') {
+          this.props.form.setFieldsValue({perspective: ''})
+        } else if (value === 'action' || value === 'colspan') {
+          this.props.form.setFieldsValue({Align: 'center'})
+        }
+      })
+    } else if (key === 'field') {
+      let values = {label: option.props.label || option.props.children}
+      if (/Decimal|int/ig.test(option.props.datatype)) {
+        let decimal = 0
+        if (/Decimal/ig.test(option.props.datatype)) {
+          decimal = +option.props.datatype.replace(/Decimal\(18,/ig, '').replace(')', '')
+        }
+        values.type = 'number'
+        values.decimal = decimal
+      } else {
+        values.type = 'text'
+      }
+
+      if (values.type !== this.state.type) {
+        values.perspective = ''
+        let _options = fromJS(columnTypeOptions[values.type]).toJS()
+
+        this.setState({
+          type: values.type,
+          formlist: this.state.formlist.map(item => {
+            item.hidden = !_options.includes(item.key)
+
+            return item
+          })
+        }, () => {
+          this.props.form.setFieldsValue(values)
+        })
+      } else {
+        this.props.form.setFieldsValue(values)
+      }
+    } else if (key === 'format' && value === 'percent') {
+      this.props.form.setFieldsValue({postfix: '%'})
+    }
+  }
+
+  changeRadio = (key, value) => {
+    if (key === 'perspective') {
+      let _options = fromJS(columnTypeOptions[this.state.type]).toJS()
+
+      if (value === 'linkmenu') {
+        _options.push('linkmenu', 'linkfields', 'open')
+      } else if (value === 'linkurl') {
+        _options.push('linkurl', 'linkfields', 'open')
+      }
+
+      this.setState({
+        formlist: this.state.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+
+          return item
+        })
+      })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const { formlist } = this.state
+    const fields = []
+
+    if (!formlist) return null
+
+    formlist.forEach((item, index) => {
+      if (item.hidden || item.forbidden) return
+
+      if (item.type === 'text') {
+        let rules = []
+        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" title={item.tooltip}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {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" title={item.tooltip}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {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 onPressEnter={this.handleSubmit}/> :
+                  <InputNumber min={item.min} max={item.max} precision={item.decimal} onPressEnter={this.handleSubmit}/>)}
+            </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, option) => {this.typeChange(item.key, value, option)}}
+                  getPopupContainer={() => document.getElementById('columnwinter')}
+                >
+                  {item.options.map((option, index) =>
+                    <Select.Option key={index} datatype={option.datatype || ''} label={option.label || ''} value={(option.value || option.field || option.MenuID)}>
+                      {(option.text || option.label || option.MenuName)}
+                    </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" title={item.tooltip}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {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.field}>{option.text || option.label}</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 || [],
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Cascader
+                  options={item.options}
+                  placeholder=""
+                  getPopupContainer={() => document.getElementById('columnwinter')}
+                />
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'textarea') {
+        fields.push(
+          <Col span={24} key={index} className="textarea">
+            <Form.Item label={item.tooltip ?
+              <Tooltip placement="topLeft" title={item.tooltip}>
+                <QuestionCircleOutlined className="mk-form-tip" />
+                {item.label}
+              </Tooltip> : item.label
+            }>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<TextArea rows={2} disabled={item.readonly} placeholder={item.placeholder || ''}/>)}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleSubmit = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    this.props.form.validateFieldsAndScroll((err, values) => {
+      if (!err) {
+        this.setState({visible: false, formlist: null})
+        this.props.submitCol(values)
+      }
+    })
+  }
+
+  editModalCancel = () => {
+    this.setState({visible: false, formlist: null})
+
+    this.props.cancelCol()
+  }
+
+  render() {
+    const { visible } = this.state
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 6 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 18 }
+      }
+    }
+
+    return (
+      <div style={{display: 'inline-block'}}>
+        <Modal
+          title="鏄剧ず鍒楃紪杈�"
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          onOk={this.handleSubmit}
+          onCancel={this.editModalCancel}
+          destroyOnClose
+        >
+          <Form {...formItemLayout} className="commontable-column-form" id="columnwinter">
+            <Row gutter={24}>{this.getFields()}</Row>
+          </Form>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(NormalTableColumn)
\ No newline at end of file
diff --git a/src/menu/components/table/base-table/columns/editColumn/index.scss b/src/menu/components/table/base-table/columns/editColumn/index.scss
new file mode 100644
index 0000000..9885df8
--- /dev/null
+++ b/src/menu/components/table/base-table/columns/editColumn/index.scss
@@ -0,0 +1,17 @@
+.commontable-column-form {
+  min-height: 190px;
+  .ant-cascader-menus {
+    padding: 5px 0px;
+    .ant-cascader-menu:last-child {
+      padding-right: 3px;
+    }
+  }
+  .textarea {
+    .ant-form-item-label {
+      width: 12%;
+    }
+    .ant-form-item-control-wrapper {
+      width: 88%;
+    }
+  }
+}
diff --git a/src/menu/components/table/base-table/columns/index.jsx b/src/menu/components/table/base-table/columns/index.jsx
new file mode 100644
index 0000000..f22548c
--- /dev/null
+++ b/src/menu/components/table/base-table/columns/index.jsx
@@ -0,0 +1,618 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { DndProvider, DragSource, DropTarget } from 'react-dnd'
+import { Table, Popover, Modal, message } from 'antd'
+import { PlusOutlined, FileSyncOutlined, EditOutlined, CopyOutlined, DeleteOutlined, FontColorsOutlined, CloseCircleOutlined, AntDesignOutlined } from '@ant-design/icons'
+
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const { confirm } = Modal
+const EditColumn = asyncIconComponent(() => import('./editColumn'))
+const MarkColumn = asyncIconComponent(() => import('@/menu/components/share/markcomponent'))
+const CardCellComponent = asyncComponent(() => import('@/menu/components/card/cardcellcomponent'))
+const MobPagination = asyncIconComponent(() => import('@/menu/components/share/mobPagination'))
+const PasteComponent = asyncIconComponent(() => import('@/components/paste'))
+
+class HeaderCol extends Component {
+  deleteCol = () => {
+    const _this = this
+
+    confirm({
+      content: '纭畾鍒犻櫎鏄剧ず鍒楀悧锛�',
+      onOk() {
+        _this.props.deleteCol(_this.props.column)
+      },
+      onCancel() {}
+    })
+  }
+
+  updateMarks = (vals) => {
+    const { column } = this.props
+    this.props.updateCol({...column, marks: vals})
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+
+    if (this.props.rowSpan !== nextProps.rowSpan || this.props.colSpan !== nextProps.colSpan) {
+      return true
+    }
+
+    if (!nextProps.column) return false
+
+    return !is(fromJS(this.props.column), fromJS(nextProps.column)) ||
+      !is(fromJS(this.props.fields), fromJS(nextProps.fields)) ||
+      this.props.index !== nextProps.index
+  }
+
+  render() {
+    const { connectDragSource, connectDropTarget, moveCol, addElement, updateCol, editColumn, pasteCell, changeStyle, deleteCol, index, column, align, fields, children, ...restProps } = this.props
+
+    if (index !== undefined) {
+      return connectDragSource(
+        connectDropTarget(<th {...restProps} index={index} style={{ cursor: 'move', textAlign: align }} onDoubleClick={() => column && this.props.editColumn(column)}>
+          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
+              {column && ['custom', 'colspan', 'action'].includes(column.type) ?
+                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
+              }
+              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+              {column && column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
+              {column && column.type === 'custom' ? <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={() => this.props.changeStyle(column)}/> : null}
+              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
+              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+            </div>
+          } trigger="hover">
+            {children}
+          </Popover>
+        </th>),
+      )
+    } else if (column) {
+      return (
+        <th {...restProps} key={column.uuid} onDoubleClick={() => this.props.editColumn(column)}>
+          <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+            <div className="mk-popover-control" onDoubleClick={(e) => e.stopPropagation()}>
+              {column && ['custom', 'colspan'].includes(column.type) ?
+                <PlusOutlined className="plus" title="娣诲姞" onClick={() => this.props.addElement(column)} /> : null
+              }
+              <EditOutlined className="edit" title="缂栬緫" onClick={() => this.props.editColumn(column)} />
+              {column.type === 'custom' ? <PasteComponent options={['customCardElement']} updateConfig={(res, resolve) => this.props.pasteCell(column, res, resolve)} /> : null}
+              <DeleteOutlined className="close" title="鍒犻櫎" onClick={this.deleteCol} />
+              {column && ['text', 'number', 'formula'].includes(column.type) ? <MarkColumn columns={fields} marks={column.marks} onSubmit={this.updateMarks} /> : null }
+            </div>
+          } trigger="hover">
+            {children}
+          </Popover>
+        </th>
+      )
+    } else {
+      return (<th {...restProps}>{children}</th>)
+    }
+  }
+}
+
+const rowSource = {
+  beginDrag(props) {
+    return {
+      index: props.index,
+    }
+  }
+}
+
+const ColTarget = {
+  drop(props, monitor) {
+    const dragIndex = monitor.getItem().index
+    const hoverIndex = props.index
+
+    if (dragIndex === undefined || hoverIndex === undefined || dragIndex === hoverIndex) {
+      return
+    }
+
+    props.moveCol(dragIndex, hoverIndex)
+    monitor.getItem().index = hoverIndex
+  },
+}
+
+const DragableHeaderCol = DropTarget('col', ColTarget, connect => ({
+  connectDropTarget: connect.dropTarget()
+}))(
+  DragSource('col', rowSource, connect => ({
+    connectDragSource: connect.dragSource(),
+  }))(HeaderCol),
+)
+
+class EditableColumnCell extends Component {
+  updateCard = (vals, btn) => {
+    const { column } = this.props
+    this.props.upComponent({...column, elements: vals}, btn)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    const { config, column } = this.props
+
+    if (!nextProps.column) return true
+
+    return !is(fromJS(column), fromJS(nextProps.column)) ||
+      !is(fromJS(config.columns), fromJS(nextProps.config.columns)) ||
+      !is(fromJS(config.action), fromJS(nextProps.config.action)) ||
+      !is(fromJS(config.search), fromJS(nextProps.config.search))
+  }
+
+  render() {
+    const { column, config, children, className, style } = this.props
+
+    if (column && column.type === 'custom') {
+      return (
+        <td style={{padding: 0, minWidth: column.Width || 100, ...(column.style || {})}} className={className}>
+          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
+        </td>
+      )
+    } else if (column && column.type === 'action') {
+      return (
+        <td style={{padding: '0 5px', textAlign: column.Align, minWidth: column.Width || 100}} className={'action-column ' + className}>
+          <CardCellComponent cards={config} cardCell={column} elements={column.elements} updateElement={this.updateCard}/>
+        </td>
+      )
+    } else if (column) {
+      let val = column.field || ''
+      if (column.type === 'index') {
+        val = '$Index'
+      } else if (column.type === 'formula') {
+        val = column.formula
+        if (column.eval === 'false') {
+          val = val.replace(/\n/ig, '<br/>').replace(/\s/ig, '&nbsp;')
+          val = <span style={{fontWeight: 'inherit'}} dangerouslySetInnerHTML={{__html: val}}></span>
+        }
+      }
+      return (
+        <td style={{...style, minWidth: column.Width || 100}} className={className}>
+          {val}
+          {column.Hide === 'true' ? <CloseCircleOutlined style={{marginLeft: '5px', color: 'orange', fontSize: '12px'}}/> : null}
+          {column.marks && column.marks.length ? <AntDesignOutlined className="profile"/> : null}
+        </td>
+      )
+    } else {
+      return (
+        <td style={style} className={className}>
+          {children}
+        </td>
+      )
+    }
+  }
+}
+
+class NormalTableColumns extends Component {
+  static propTpyes = {
+    config: PropTypes.object,       // 閰嶇疆淇℃伅
+    updatecolumn: PropTypes.func    // 鏁版嵁鍙樺寲
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    appType: sessionStorage.getItem('appType'),
+    tableId: '',
+    data: [{uuid: Utils.getuuid()}],
+    refresh: false,    // 寮哄埗鍒锋柊
+    columns: [],
+    fields: [],
+    editStyleCard: null,
+    lineMarks: []
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    let tableId = (() => {
+      let uuid = []
+      let _options = 'abcdefghigklmnopqrstuv'
+      for (let i = 0; i < 19; i++) {
+        uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1))
+      }
+      return uuid.join('')
+    }) ()
+
+    this.setState({
+      tableId,
+      columns: fromJS(config.cols).toJS(),
+      fields: fromJS(config.columns).toJS(),
+      lineMarks: config.lineMarks ? fromJS(config.lineMarks).toJS() : []
+    }, () => {
+      const element = document.getElementById(tableId)
+      element && element.style.setProperty('--mk-table-border-color', config.wrap.borderColor || '#e8e8e8')
+      element && element.style.setProperty('--mk-table-color', config.wrap.color || 'rgba(0, 0, 0, 0.65)')
+      element && element.style.setProperty('--mk-table-font-size', config.wrap.fontSize || '14px')
+      element && element.style.setProperty('--mk-table-font-weight', config.wrap.fontWeight || 'normal')
+    })
+  }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.state.columns), fromJS(nextProps.config.cols))) {
+      let _columns = fromJS(nextProps.config.cols).toJS()
+      this.setState({columns: _columns})
+      let lastcol = _columns.slice(-1)[0]
+      if (lastcol && lastcol.focus) {
+        this.editColumn(lastcol)
+      }
+    } else if (!is(fromJS(this.state.fields), fromJS(nextProps.config.columns))) {
+      this.setState({fields: fromJS(nextProps.config.columns).toJS()})
+    } else if (!is(fromJS(this.props.config.wrap), fromJS(nextProps.config.wrap))) {
+      const element = document.getElementById(this.state.tableId)
+      element && element.style.setProperty('--mk-table-border-color', nextProps.config.wrap.borderColor || '#e8e8e8')
+      element && element.style.setProperty('--mk-table-color', nextProps.config.wrap.color || 'rgba(0, 0, 0, 0.65)')
+      element && element.style.setProperty('--mk-table-font-size', nextProps.config.wrap.fontSize || '14px')
+      element && element.style.setProperty('--mk-table-font-weight', nextProps.config.wrap.fontWeight || 'normal')
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    const { config } = this.props
+
+    return !is(fromJS(this.state), fromJS(nextState)) ||
+      !is(fromJS(config.wrap), fromJS(nextProps.config.wrap)) ||
+      !is(fromJS(config.search), fromJS(nextProps.config.search)) ||
+      !is(fromJS(config.action), fromJS(nextProps.config.action)) ||
+      config.setting.laypage !== nextProps.config.setting.laypage
+  }
+
+  moveCol = (dragIndex, hoverIndex) => {
+    let _columns = fromJS(this.state.columns).toJS()
+
+    _columns.splice(hoverIndex, 0, ..._columns.splice(dragIndex, 1))
+
+    this.setState({
+      columns: _columns
+    }, () => {
+      this.props.updatecolumn({...this.props.config, cols: _columns})
+    })
+  }
+
+  loopCol = (columns, col) => {
+    return columns.map(column => {
+      if (column.type === 'colspan') {
+        column.subcols = this.loopCol(column.subcols, col)
+      }
+      if (column.uuid === col.uuid) {
+        return col
+      }
+      return column
+    })
+  }
+
+  updateCol = (col, btn) => {
+    let _columns = fromJS(this.state.columns).toJS()
+    _columns = this.loopCol(_columns, col)
+
+    this.setState({
+      columns: _columns,
+    }, () => {
+      let config = {...this.props.config, cols: _columns}
+      if (btn) {
+        config.action = config.action.filter(item => item.uuid !== btn.uuid)
+      }
+
+      this.props.updatecolumn(config)
+    })
+  }
+
+  editColumn = (col) => {
+    this.setState({
+      card: fromJS(col).toJS()
+    })
+  }
+
+  pasteCell = (col, cell, resolve) => {
+    resolve({status: true})
+    
+    delete cell.copyType
+    cell.uuid = Utils.getuuid()
+    cell.focus = true
+    
+    MKEmitter.emit('cardAddElement', [this.props.config.uuid, col.uuid], cell)
+  }
+
+  addElement = (col) => {
+    const { config } = this.props
+    let column = fromJS(col).toJS()
+
+    if (column.type === 'colspan') {
+      column.subcols = column.subcols || []
+      let subcol = { isSub: true, focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' }
+      column.subcols.push(subcol)
+
+      this.setState({
+        card: subcol
+      })
+      this.updateCol(column)
+    } else if (column.type === 'custom') {
+      let newcard = {uuid: Utils.getuuid(), focus: true, width: 24, eleType: 'text', datatype: 'dynamic', style: {paddingLeft: '4px'}}
+  
+      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+      MKEmitter.emit('cardAddElement', [config.uuid, column.uuid], newcard)
+    } else if (column.type === 'action') {
+      let newcard = {
+        uuid: Utils.getuuid(),
+        focus: true,
+        eleType: 'button',
+        label: 'button',
+        OpenType: 'prompt',
+        class: 'primary',
+        intertype: 'system',
+        execSuccess: 'grid',
+        execError: 'never',
+        show: 'link'
+      }
+
+      // 娉ㄥ唽浜嬩欢-娣诲姞鍏冪礌
+      MKEmitter.emit('cardAddElement', [config.uuid, column.uuid], newcard)
+    }
+  }
+
+  submitCol = (col) => {
+    const { card } = this.state
+
+    col.uuid = card.uuid
+    col.isSub = card.isSub === true
+    col.marks = card.marks || []
+    
+    if (col.type === 'colspan') {
+      col.subcols = card.subcols || []
+    } else if (col.type === 'custom') {
+      col.elements = card.type === 'custom' ? (card.elements || []) : []
+    } else if (col.type === 'action') {
+      col.elements = card.type === 'action' ? (card.elements || []) : []
+    }
+
+    this.setState({card: null})
+    this.updateCol(col)
+  }
+
+  changeStyle = (col) => {
+    this.setState({
+      editStyleCard: fromJS(col).toJS()
+    })
+
+    MKEmitter.emit('changeStyle', ['font', 'padding'], col.style || {}, this.getStyle)
+  }
+
+  getStyle = (style) => {
+    const { editStyleCard } = this.state
+
+    let _card = {...editStyleCard, style}
+    
+    this.updateCol(_card)
+  }
+
+  cancelCol = () => {
+    const { card } = this.state
+
+    if (card.focus) {
+      this.deleteCol(card)
+    }
+
+    this.setState({card: null})
+  }
+
+  loopDelCol = (columns, col) => {
+    return columns.filter(column => {
+      if (column.type === 'colspan') {
+        column.subcols = this.loopDelCol(column.subcols, col)
+      }
+      return column.uuid !== col.uuid
+    })
+  }
+
+  deleteCol = (col) => {
+    const { appType } = this.state
+    let _columns = fromJS(this.state.columns).toJS()
+
+    _columns = this.loopDelCol(_columns, col)
+
+    this.setState({
+      columns: _columns
+    }, () => {
+      this.props.updatecolumn({...this.props.config, cols: _columns})
+    })
+
+    if (col.type !== 'action' || appType === 'mob') return
+
+    let uuids = []
+    col.elements && col.elements.forEach(c => {
+      if (appType === 'pc' && c.OpenType !== 'popview') return
+
+      uuids.push(c.uuid)
+    })
+
+    if (uuids.length === 0) return
+    
+    MKEmitter.emit('delButtons', uuids)
+  }
+
+  updateLineMarks = (vals) => {
+    this.setState({
+      lineMarks: vals
+    }, () => {
+      this.props.updatecolumn({...this.props.config, lineMarks: vals})
+    })
+  }
+
+  /**
+   * @description 鏄剧ず鍒楀鍒�
+   */
+  copycolumn = () => {
+    const { columns } = this.state
+
+    let oInput = document.createElement('input')
+    let val = {
+      copyType: 'cols',
+      cols: columns.filter(col => !col.origin)
+    }
+
+    let srcid = localStorage.getItem(window.location.href.split('#')[0] + 'srcId')
+    if (srcid) {
+      val.$srcId = srcid
+    }
+
+    oInput.value = window.btoa(window.encodeURIComponent(JSON.stringify(val)))
+    document.body.appendChild(oInput)
+    oInput.select()
+    document.execCommand('Copy')
+    oInput.className = 'oInput'
+    oInput.style.display = 'none'
+
+    message.success('澶嶅埗鎴愬姛銆�')
+
+    document.body.removeChild(oInput)
+  }
+
+  handlecolumns = (columns, fields, config, isSub) => {
+    return columns.map((col, index) => {
+      return {
+        title: col.label,
+        dataIndex: col.uuid,
+        align: col.Align,
+        // sorter: !isSub && col.IsSort === 'true',
+        sorter: col.IsSort === 'true',
+        onCell: () => ({
+          column: col,
+          width: col.Width,
+          config: config,
+          upComponent: this.updateCol
+        }),
+        onHeaderCell: () => ({
+          index: isSub ? undefined : index,
+          column: col,
+          fields: fields,
+          align: col.Align,
+          moveCol: this.moveCol,
+          updateCol: this.updateCol,
+          addElement: this.addElement,
+          editColumn: this.editColumn,
+          pasteCell: this.pasteCell,
+          changeStyle: this.changeStyle,
+          deleteCol: this.deleteCol,
+        }),
+        children: col.subcols && col.subcols.length ? this.handlecolumns(col.subcols, fields, config, true) : null,
+      }
+    })
+  }
+
+  syncfield = () => {
+    const { fields } = this.state
+    let columns = fromJS(this.state.columns).toJS()
+
+    columns = columns.filter(c => !c.origin)
+
+    let keys = columns.map(col => col.field)
+
+    fields.forEach(item => {
+      if (keys.includes(item.field)) return
+
+      let cell = { uuid: Utils.getuuid(), label: item.label, field: item.field, Align: 'left', Hide: 'false', IsSort: 'true', Width: 120, blacklist: [], postfix: '', prefix: '', linkmenu: [], marks: [], perspective: 'linkmenu' }
+      
+      if (/Nvarchar|date/ig.test(item.datatype)) {
+        cell.type = 'text'
+        cell.rowspan = 'false'
+        cell.textFormat = 'none'
+      } else {
+        cell.type = 'number'
+        cell.format = 'none'
+        cell.sum = 'false'
+        cell.decimal = item.decimal || 0
+        cell.Width = 80
+      }
+
+      columns.push(cell)
+    })
+
+    const _this = this
+
+    confirm({
+      content: '纭畾鍚屾瀛楁闆嗗悧锛�',
+      onOk() {
+        _this.setState({columns}, () => {
+          _this.props.updatecolumn({..._this.props.config, cols: columns})
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  clear = () => {
+    const _this = this
+
+    confirm({
+      content: '纭畾娓呯┖鏄剧ず鍒楀悧锛�',
+      onOk() {
+        _this.setState({columns: []}, () => {
+          _this.props.updatecolumn({..._this.props.config, cols: []})
+        })
+      },
+      onCancel() {}
+    })
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+  }
+
+  render() {
+    const { config } = this.props
+    const { fields, card, lineMarks, dict, tableId, appType } = this.state
+    const components = {
+      header: {
+        cell: DragableHeaderCol
+      },
+      body: {
+        cell: EditableColumnCell
+      }
+    }
+
+    const columns = this.handlecolumns(this.state.columns, fields, config)
+
+    return (
+      <div className={`normal-table-columns ${config.setting.laypage} ${config.wrap.tableType} ${config.wrap.mode || ''}`} id={tableId}>
+        <div className="col-control">
+          <CopyOutlined title="澶嶅埗鏄剧ず鍒�" onClick={this.copycolumn} />
+          <MarkColumn columns={fields} type="line" marks={lineMarks} onSubmit={this.updateLineMarks} />
+          <FileSyncOutlined title="鍚屾瀛楁闆�" onClick={this.syncfield} />
+          <DeleteOutlined title="娓呯┖鏄剧ず鍒�" onClick={this.clear}/>
+        </div>
+        <DndProvider>
+          <Table
+            rowKey="uuid"
+            size={config.wrap.size || 'middle'}
+            rowClassName="editable-row"
+            bordered={config.wrap.bordered !== 'false'}
+            components={components}
+            dataSource={this.state.data}
+            rowSelection={config.wrap.tableType ? { type: 'radio' } : null}
+            columns={columns}
+            pagination={appType !== 'mob' ? {
+              current: 1,
+              pageSize: 10,
+              pageSizeOptions: ['10', '25', '50', '100', '500', '1000'],
+              showSizeChanger: true,
+              total: 58,
+              showTotal: (total, range) => `${range[0]}-${range[1]} 鍏� ${total} 鏉
+            } : false}
+          />
+          {appType === 'mob' && config.setting.laypage !== 'fasle' ? <MobPagination /> : null}
+        </DndProvider>
+        <EditColumn column={card} dict={dict} fields={fields} submitCol={this.submitCol} cancelCol={this.cancelCol}/>
+      </div>
+    )
+  }
+}
+
+export default NormalTableColumns
\ No newline at end of file
diff --git a/src/menu/components/table/base-table/columns/index.scss b/src/menu/components/table/base-table/columns/index.scss
new file mode 100644
index 0000000..3d4835c
--- /dev/null
+++ b/src/menu/components/table/base-table/columns/index.scss
@@ -0,0 +1,146 @@
+.normal-table-columns {
+  position: relative;
+  --mk-table-border-color: #e8e8e8;
+  --mk-table-color: rgba(0, 0, 0, 0.65);
+  --mk-table-font-size: 14px;
+  --mk-table-font-weight: normal;
+
+  .ant-table {
+    color: inherit;
+    font-size: inherit;
+    font-weight: inherit;
+  }
+  .ant-table-body {
+    overflow-x: auto;
+    tr {
+      td {
+        background: #ffffff;
+      }
+      td:not(.ant-table-selection-column) {
+        position: relative;
+        padding: 12px 8px;
+        >.profile {
+          position: absolute;
+          top: 2px;
+          right: 2px;
+          color: purple;
+          font-size: 12px;
+        }
+      }
+    }
+    .action-column {
+      .card-detail-row:empty {
+        min-height: 40px;
+      }
+    }
+    tr:hover td {
+      background: #ffffff!important;
+    }
+  }
+
+  .ant-table-thead {
+    th {
+      position: relative;
+      .ant-table-column-sorter::before {
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 0;
+        content: '';
+      }
+    }
+    > tr > th {
+      padding: 12px 8px;
+      .ant-table-column-sorter .ant-table-column-sorter-inner {
+        .ant-table-column-sorter-up.on, .ant-table-column-sorter-down.on {
+          color: unset;
+        }
+      }
+    }
+  }
+  .col-control {
+    position: absolute;
+    z-index: 2;
+    right: 0;
+    top: -25px;
+    >.anticon, >div > .anticon {
+      font-size: 16px;
+      margin-right: 10px;
+      cursor: pointer;
+    }
+    >.anticon-copy {
+      color: #26C281;
+    }
+    >.anticon-delete {
+      color: #ff4d4f;
+    }
+    >.anticon-file-sync {
+      color: #1890ff;
+    }
+    >div >.profile {
+      color: purple;
+    }
+  }
+  .ant-table-small > .ant-table-content > .ant-table-body {
+    margin: 0;
+  }
+
+  table, tr, th, td {
+    border-color: var(--mk-table-border-color)!important;
+  }
+  table tr {
+    th .ant-table-column-title {
+      // color: var(--mk-table-color)!important;
+      font-size: var(--mk-table-font-size)!important;
+      font-weight: var(--mk-table-font-weight)!important;
+    }
+    td {
+      color: var(--mk-table-color)!important;
+      font-size: var(--mk-table-font-size)!important;
+      font-weight: var(--mk-table-font-weight)!important;
+    }
+  }
+}
+.normal-table-columns.false {
+  .ant-pagination {
+    display: none;
+  }
+}
+.normal-table-columns.checkbox {
+  .ant-radio-inner {
+    border-radius: 0;
+  }
+  .ant-radio-inner::after {
+    border-radius: 0;
+  }
+  .ant-radio-checked::after {
+    border-radius: 0;
+  }
+}
+
+.normal-table-columns.ghost {
+  .ant-table-thead > tr {
+    > th {
+      color: inherit;
+      background: transparent;
+      .ant-table-column-sorter .ant-table-column-sorter-inner {
+        color: inherit;
+      }
+    }
+    > th:hover {
+      background: transparent;
+    }
+  }
+  .ant-table-body {
+    overflow-x: auto;
+    tr {
+      td {
+        background: transparent;
+      }
+    }
+    tr:hover td {
+      background: transparent!important;
+    }
+  }
+}
diff --git a/src/menu/components/table/base-table/index.jsx b/src/menu/components/table/base-table/index.jsx
new file mode 100644
index 0000000..480a7db
--- /dev/null
+++ b/src/menu/components/table/base-table/index.jsx
@@ -0,0 +1,554 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Popover } from 'antd'
+import { PlusOutlined, PlusCircleOutlined, PlusSquareOutlined, EditOutlined, ToolOutlined, DeleteOutlined, FontColorsOutlined } from '@ant-design/icons'
+
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import { resetStyle } from '@/utils/utils-custom.js'
+import MKEmitter from '@/utils/events.js'
+import getWrapForm from './options'
+import Utils from '@/utils/utils.js'
+
+import './index.scss'
+
+const SettingComponent = asyncIconComponent(() => import('@/menu/datasource'))
+const NormalForm = asyncIconComponent(() => import('@/components/normalform'))
+const SearchComponent = asyncComponent(() => import('@/templates/sharecomponent/searchcomponent'))
+const ActionComponent = asyncComponent(() => import('@/menu/components/share/actioncomponent'))
+const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
+const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
+const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
+// const LogComponent = asyncIconComponent(() => import('@/menu/components/share/logcomponent'))
+const ColumnComponent = asyncComponent(() => import('./columns'))
+
+class TableCardEditComponent extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    deletecomponent: PropTypes.func,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    appType: sessionStorage.getItem('appType'),
+    card: null,
+    back: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+    const { appType } = this.state
+
+    if (card.isNew) {
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        tabId: card.tabId || '',
+        parentId: card.parentId || '',
+        format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+        pageable: true,     // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+        switchable: true,   // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+        dataName: card.dataName || '',
+        width: card.width || 24,
+        search: [
+          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text', match: 'like' },
+          { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: 'equal' }
+        ],
+        action: [
+          { origin: true, uuid: Utils.getuuid(), label: '娣诲姞', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} },
+          { origin: true, uuid: Utils.getuuid(), label: '淇敼', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'form', class: 'purple', style: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} },
+          { origin: true, uuid: Utils.getuuid(), label: '鍒犻櫎', intertype: 'system', OpenType: 'prompt', execSuccess: 'grid', Ot: 'required', icon: 'delete', class: 'danger', style: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} }
+        ],
+        name: card.name,
+        subtype: card.subtype,
+        setting: { interType: 'system' },
+        wrap: { name: card.name, width: card.width || 24, bordered: 'true', tableType: 'checkbox', show: 'true' },
+        style: { marginLeft: '8px', marginRight: '8px', marginTop: '8px', marginBottom: '8px' },
+        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+        columns: [],
+        cols: [
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label1', field: '', Hide: 'false', type: 'text', Width: 120 },
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label2', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+          { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+        ],
+        scripts: [],
+        btnlog: [],
+        isNew: true
+      }
+
+      if (card.config) {
+        let config = fromJS(card.config).toJS()
+
+        _card.wrap = config.wrap
+        _card.wrap.name = card.name
+        _card.style = config.style
+        _card.headerStyle = config.headerStyle
+
+        _card.setting = config.setting
+        _card.columns = config.columns
+        _card.scripts = config.scripts
+
+        let oriUids = {}
+        _card.action = config.action.map(item => {
+          let _uuid = Utils.getuuid()
+          oriUids[item.uuid] = _uuid
+          item.uuid = _uuid
+          return item
+        })
+        _card.search = config.search.map(item => {
+          item.uuid = Utils.getuuid()
+          return item
+        })
+        _card.cols = config.cols.map(col => {
+          col.uuid = Utils.getuuid()
+          if (col.type === 'colspan' && col.subcols) {
+            col = this.loopCol(col)
+          } else if (col.type === 'custom' && col.elements) {
+            col.elements = col.elements.map(cell => {
+              cell.uuid = Utils.getuuid()
+              return cell
+            })
+          } else if (col.type === 'action' && col.elements) {
+            col.elements = col.elements.map(cell => {
+              cell.uuid = Utils.getuuid()
+              return cell
+            })
+          }
+          return col
+        })
+        
+        if (_card.wrap.doubleClick) {
+          _card.wrap.doubleClick = oriUids[_card.wrap.doubleClick] || ''
+        }
+      }
+
+      if (appType === 'mob') {
+        _card.search = []
+        _card.action = _card.action.filter(a => !a.origin)
+      }
+
+      this.updateComponent(_card)
+    } else {
+      let _card = fromJS(card).toJS()
+      if (appType === 'mob') {
+        _card.search = []
+      }
+
+      this.setState({
+        card: _card
+      })
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('submitModal', this.handleSave)
+    // MKEmitter.addListener('logButton', this.logButton)
+    MKEmitter.addListener('completeSave', this.completeSave)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('submitModal', this.handleSave)
+    // MKEmitter.removeListener('logButton', this.logButton)
+    MKEmitter.removeListener('completeSave', this.completeSave)
+  }
+
+  completeSave = () => {
+    const { card } = this.state
+
+    if (card.isNew) {
+      let item = fromJS(card).toJS()
+      item.search = item.search.filter(a => !a.origin)
+      item.action = item.action.filter(a => !a.origin)
+      item.cols = item.cols.filter(a => !a.origin)
+
+      delete item.isNew
+
+      this.setState({card: item}, () => { MKEmitter.emit('revert') })
+    }
+  }
+
+  loopCol = (col) => {
+    col.subcols = col.subcols.map(c => {
+      c.uuid = Utils.getuuid()
+      if (c.type === 'colspan' && c.subcols) {
+        c = this.loopCol(c)
+      } else if (c.type === 'custom' && c.elements) {
+        c.elements = c.elements.map(cell => {
+          cell.uuid = Utils.getuuid()
+          return cell
+        })
+      }
+      return c
+    })
+
+    return col
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (card) => {
+    card.width = card.wrap.width
+    card.name = card.wrap.name
+
+    if (!window.GLOB.styling || !card.errors) { // 鏍峰紡淇敼鏃朵笉鍋氱瓫鏌�
+      card.errors = []
+
+      // let supModule = card.setting.supModule ? card.setting.supModule[card.setting.supModule.length - 1] || '' : ''
+      // if (supModule === 'empty') {
+      //   supModule = ''
+      // }
+      let doubleClick = card.wrap.doubleClick || ''
+  
+      let columns = card.columns.map(c => c.field)
+      // let lowcols = card.columns.map(c => c.field.toLowerCase())
+  
+      if (card.setting.interType === 'system' && card.setting.execute !== 'false' && !card.setting.dataresource) {
+        card.errors.push({ level: 0, detail: '鏈缃暟鎹簮锛�'})
+      } else if (card.setting.interType === 'system' && card.setting.execute === 'false' && card.scripts.filter(script => script.status !== 'false').length === 0) {
+        card.errors.push({ level: 0, detail: '鏁版嵁婧愪腑鏃犲彲鐢ㄨ剼鏈紒'})
+      } else if (!card.setting.primaryKey) {
+        card.errors.push({ level: 0, detail: '鏈缃富閿紒'})
+      } else if (!columns.includes(card.setting.primaryKey)) {
+        card.errors.push({ level: 0, detail: '涓婚敭宸插け鏁堬紒'})
+      } else if (!card.setting.supModule) {
+        card.errors.push({ level: 0, detail: '鏈缃笂绾х粍浠讹紒'})
+      }
+
+      card.action.forEach(cell => {
+        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+          if (!cell.modal || cell.modal.fields.length === 0) {
+            card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+          // } else {
+          //   cell.modal.fields.forEach(m => {
+          //     if (m.type === 'linkMain' && !supModule) {
+          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
+          //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
+          //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
+          //     }
+          //   })
+          }
+        }
+        if (doubleClick === cell.uuid) {
+          doubleClick = ''
+        }
+      })
+  
+      card.cols.forEach(col => {
+        if (col.type === 'action') {
+          col.elements.forEach(cell => {
+            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
+              if (!cell.modal || cell.modal.fields.length === 0) {
+                card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟灏氭湭娣诲姞`})
+              // } else {
+              //   cell.modal.fields.forEach(m => {
+              //     if (m.type === 'linkMain' && !supModule) {
+              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑鍏宠仈涓昏〃琛ㄥ崟鈥�${m.label}鈥濇棤鏁坄})
+              //     } else if (m.field && !columns.includes(m.field) && lowcols.includes(m.field.toLowerCase())) {
+              //       card.errors.push({ level: 1, detail: `鎸夐挳鈥�${cell.label}鈥濅腑琛ㄥ崟鈥�${m.label}鈥濆ぇ灏忓啓涓庡瓧娈甸泦涓嶄竴鑷碻})
+              //     }
+              //   })
+              }
+            }
+            if (doubleClick === cell.uuid) {
+              doubleClick = ''
+            }
+          })
+        } else if (col.type === 'custom') {
+          col.elements.forEach(cell => {
+            if (cell.datatype === 'dynamic' && cell.field && !columns.includes(cell.field)) {
+              card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑鍔ㄦ�佸瓧娈碘��${cell.field}鈥濇棤鏁坄})
+            }
+          })
+        } else if (col.field && !columns.includes(col.field)) {
+          card.errors.push({ level: 1, detail: `鏄剧ず鍒椻��${col.label}鈥濅腑瀛楁鈥�${col.field}鈥濇棤鏁坄})
+        }
+      })
+      
+      if (doubleClick) {
+        card.errors.push({ level: 1, detail: `缁戝畾鐨勫弻鍑绘寜閽凡鍒犻櫎`})
+      }
+    }
+
+    this.setState({
+      card: card
+    })
+
+    let _card = card.isNew ? fromJS(card).toJS() : card
+    if (_card.isNew) {
+      _card.cols = _card.cols.filter(a => !a.origin)
+      _card.search = _card.search.filter(a => !a.origin)
+      _card.action = _card.action.filter(a => !a.origin)
+
+      delete _card.isNew
+    }
+    
+    this.props.updateConfig(_card)
+  }
+
+  // logButton = (id, item) => {
+  //   const { card } = this.state
+
+  //   if (id !== card.uuid) return
+
+  //   let btnlog = card.btnlog || []
+  //   btnlog.push(item)
+
+  //   this.updateComponent({...card, btnlog})
+  // }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    let style = {...card.style}
+    style.color = card.wrap.color || 'rgba(0, 0, 0, 0.65)'
+    style.fontSize = card.wrap.fontSize || 14
+    style.fontWeight = card.wrap.fontWeight || 'normal'
+
+    MKEmitter.emit('changeStyle', ['font1', 'background', 'border', 'padding', 'margin', 'shadow'], style, this.getStyle)
+  }
+
+  getStyle = (style) => {
+    const { card } = this.state
+
+    let _card = fromJS(card).toJS()
+    let _style = fromJS(style).toJS()
+
+    let color = style.color
+    let fontSize = style.fontSize
+    let fontWeight = style.fontWeight
+
+    delete _style.color
+    delete _style.fontSize
+    delete _style.fontWeight
+
+    _card.style = _style
+    _card.wrap.color = color
+    _card.wrap.fontSize = fontSize
+    _card.wrap.fontWeight = fontWeight
+
+    this.updateComponent(_card)
+  }
+
+  addColumns = () => {
+    let card = fromJS(this.state.card).toJS()
+
+    card.cols.push({ focus: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text' })
+
+    this.setState({card})
+  }
+
+  addSearch = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('plusSearch', card.uuid, {uuid: Utils.getuuid(), focus: true, label: 'label', type: 'text', match: '='}, 'simple')
+  }
+
+  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.verify = null
+    newcard.show = 'button'
+    newcard.style = {marginRight: '15px'}
+
+    // 娉ㄥ唽浜嬩欢-娣诲姞鎸夐挳
+    MKEmitter.emit('addButton', card.uuid, newcard)
+  }
+
+  setSubConfig = (item) => {
+    const { card, appType } = this.state
+    let btn = fromJS(item).toJS()
+
+    if (btn.OpenType === 'pop' || btn.execMode === 'pop') {
+      if (!btn.modal) {
+        btn.modal = {
+          setting: { title: btn.label, width: appType === 'mob' ? 100 : 60, cols: '2', container: 'view', focus: '', finish: 'close', clickouter: 'unclose', display: 'modal' },
+          tables: [],
+          groups: [],
+          fields: []
+        }
+      }
+      MKEmitter.emit('changeModal', card, btn)
+    } else if (btn.OpenType === 'popview') {
+      MKEmitter.emit('changePopview', card, btn)
+    }
+  }
+
+  handleSave = (_cards, btn, modal) => {
+    let card = fromJS(this.state.card).toJS()
+
+    if (card.uuid !== _cards.uuid) return
+
+    let _index = card.action.findIndex(cell => cell.uuid === btn.uuid)
+
+    if (_index === -1) return
+
+    card.action = card.action.map(cell => {
+      if (cell.uuid === btn.uuid) {
+        cell.modal = modal
+      }
+
+      return cell
+    })
+
+    this.updateComponent(card)
+  }
+
+  // handleLog = (type, logs, item) => {
+  //   let card = fromJS(this.state.card).toJS()
+
+  //   if (type === 'revert') {
+  //     let done = false
+  //     if (item.$parentId) {
+  //       card.cols.forEach(col => {
+  //         if (col.type !== 'action') return
+  //         if (item.$parentId === col.uuid) {
+  //           col.elements = col.elements ? [...col.elements, item] : [item]
+  //           done = true
+  //         }
+  //       })
+  //     }
+
+  //     if (!done) {
+  //       card.action = card.action ? [...card.action, item] : [item]
+  //     }
+
+  //     card.btnlog = logs
+
+  //     this.updateComponent(card)
+  //     notification.success({
+  //       top: 92,
+  //       message: '鎭㈠鎴愬姛锛�',
+  //       duration: 2
+  //     })
+  //   } else {
+  //     card.btnlog = logs
+  //     this.updateComponent(card)
+  //     notification.success({
+  //       top: 92,
+  //       message: '娓呴櫎鎴愬姛锛�',
+  //       duration: 2
+  //     })
+  //   }
+  // }
+
+  getWrapForms = () => {
+    const { wrap, action, columns, cols } = this.state.card
+
+    let _actions = [...action]
+
+    cols.forEach(col => {
+      if (col.type !== 'action') return
+      _actions.push(...col.elements)
+    })
+
+    return getWrapForm(wrap, _actions, columns)
+  }
+
+  updateWrap = (res) => {
+    const { card } = this.state
+
+    res.color = card.wrap.color
+    res.fontSize = card.wrap.fontSize
+    res.fontWeight = card.wrap.fontWeight
+
+    res.show = card.wrap.show || 'true'
+    res.advanceType = card.wrap.advanceType || 'modal'
+    res.advanceWidth = card.wrap.advanceWidth || 1000
+    res.drawerPlacement = card.wrap.drawerPlacement || 'right'
+    res.searchRatio = card.wrap.searchRatio || 6
+    res.searchLwidth = card.wrap.searchLwidth !== undefined ? card.wrap.searchLwidth : 33.3
+
+    this.updateComponent({...card, wrap: res})
+  }
+
+  clickComponent = (e) => {
+    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
+      e.stopPropagation()
+      MKEmitter.emit('clickComponent', this.state.card)
+    }
+  }
+
+  render() {
+    const { card, appType } = this.state
+    let options = ['action', 'search', 'form', 'cols']
+    let _style = resetStyle(card.style)
+    
+    if (appType === 'mob') {
+      options = ['action', 'cols']
+    }
+
+    return (
+      <div className="menu-normal-table-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
+        <NormalHeader hideSearch="true" config={card} updateComponent={this.updateComponent}/>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <PlusOutlined className="plus" title="娣诲姞鍒�" onClick={this.addColumns}/>
+            {appType !== 'mob' ? <PlusCircleOutlined className="plus" title="娣诲姞鎼滅储" onClick={this.addSearch}/> : null}
+            <PlusSquareOutlined className="plus" title="娣诲姞鎸夐挳" onClick={this.addButton}/>
+            <NormalForm title="琛ㄦ牸璁剧疆" width={800} update={this.updateWrap} getForms={this.getWrapForms}>
+              <EditOutlined style={{color: '#1890ff'}} title="缂栬緫"/>
+            </NormalForm>
+            <CopyComponent type="normaltable" card={card}/>
+            <PasteComponent config={card} options={options} updateConfig={this.updateComponent} />
+            <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/>
+            {/* <LogComponent btnlog={card.btnlog || []} handlelog={this.handleLog} /> */}
+            <UserComponent config={card}/>
+            <DeleteOutlined className="close" title="鍒犻櫎缁勪欢" onClick={() => this.props.deletecomponent(card.uuid)} />
+            <SettingComponent config={card} updateConfig={this.updateComponent} />
+          </div>
+        } trigger="hover">
+          <ToolOutlined />
+        </Popover>
+        <SearchComponent config={card} updatesearch={this.updateComponent}/>
+        <ActionComponent config={card} setSubConfig={this.setSubConfig} updateaction={this.updateComponent}/>
+        <ColumnComponent config={card} updatecolumn={this.updateComponent}/>
+        <div className="component-name">
+          <div className="center">
+            <div className="title">{card.name}</div>
+            <div className="content">
+              {card.errors && card.errors.map((err, index) => {
+                if (err.level === 0) {
+                  return <span key={index} className="error">{err.detail}</span>
+                } else {
+                  return <span key={index} className="waring">{err.detail}锛�</span>
+                }
+              })}
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default TableCardEditComponent
\ No newline at end of file
diff --git a/src/menu/components/table/base-table/index.scss b/src/menu/components/table/base-table/index.scss
new file mode 100644
index 0000000..b558c2a
--- /dev/null
+++ b/src/menu/components/table/base-table/index.scss
@@ -0,0 +1,92 @@
+.menu-normal-table-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 100px;
+  
+  .model-table-search-list {
+    padding: 10px 0px 15px;
+    min-height: 65px;
+    border-bottom: 1px solid #f0f0f0;
+    .page-card {
+      background: transparent;
+    }
+    .quickly-add {
+      display: inline-block;
+      position: absolute;
+      z-index: 3;
+      right: 70px;
+      bottom: 5px;
+      .ant-btn-block {
+        background-color: transparent;
+        color: #1890ff;
+        border: none;
+        box-shadow: none !important;
+        height: 18px;
+        padding: 0 10px;
+      }
+    }
+  }
+  .model-table-search-list.length0 {
+    min-height: 10px;
+    border-bottom: 0;
+    >.quickly-add {
+      right: unset;
+      left: -8px;
+      bottom: 0;
+    }
+    >.ant-row {
+      display: none;
+    }
+    >.ant-switch {
+      display: none;
+    }
+  }
+  .model-table-search-list.length0 + .length0 {
+    margin-top: -25px;
+  }
+  .anticon-tool {
+    position: absolute;
+    z-index: 2;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+  .model-menu-action-list {
+    line-height: 55px;
+    padding: 0px;
+    min-height: 55px;
+    >.ant-row {
+      min-height: 30px;
+    }
+  }
+  .card-add-button {
+    text-align: right;
+    clear: left;
+    .anticon-plus {
+      font-size: 20px;
+      color: #26C281;
+      padding: 5px;
+      margin-right: 10px;
+    }
+  }
+
+  .ant-btn.mk-link {
+    padding: 0;
+  }
+}
+.menu-normal-table-edit-box::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.menu-normal-table-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/menu/components/table/base-table/options.jsx b/src/menu/components/table/base-table/options.jsx
new file mode 100644
index 0000000..c6caecc
--- /dev/null
+++ b/src/menu/components/table/base-table/options.jsx
@@ -0,0 +1,274 @@
+/**
+ * @description Wrap琛ㄥ崟閰嶇疆淇℃伅
+ */
+export default function (wrap, action = [], columns = []) {
+  let roleList = sessionStorage.getItem('sysRoles')
+  let appType = sessionStorage.getItem('appType')
+
+  if (roleList) {
+    try {
+      roleList = JSON.parse(roleList)
+    } catch (e) {
+      roleList = []
+    }
+  } else {
+    roleList = []
+  }
+
+  const wrapForm = [
+    {
+      type: 'text',
+      field: 'title',
+      label: '鏍囬',
+      initval: wrap.title || '',
+      required: false
+    },
+    {
+      type: 'text',
+      field: 'name',
+      label: '缁勪欢鍚嶇О',
+      initval: wrap.name || '',
+      tooltip: '鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�',
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'width',
+      label: '瀹藉害',
+      initval: wrap.width || 24,
+      tooltip: '鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��',
+      min: 1,
+      max: 24,
+      precision: 0,
+      required: true
+    },
+    {
+      type: 'number',
+      field: 'height',
+      label: '楂樺害',
+      initval: wrap.height || '',
+      tooltip: '琛ㄦ牸楂樺害锛岀┖鍊兼椂楂樺害鑷�傚簲銆�',
+      min: 10,
+      max: 3000,
+      precision: 0,
+      required: false,
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'radio',
+      field: 'tableType',
+      label: '琛ㄦ牸灞炴��',
+      initval: wrap.tableType || '',
+      required: false,
+      options: [
+        {value: '', label: '涓嶅彲閫�'},
+        {value: 'radio', label: '鍗曢��'},
+        {value: 'checkbox', label: '澶氶��'},
+      ],
+      controlFields: [
+        {field: 'selected', values: ['radio', 'checkbox']},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'bordered',
+      label: '杈规',
+      initval: wrap.bordered || 'true',
+      required: false,
+      options: [
+        {value: 'true', label: '鏈�'},
+        {value: 'false', label: '鏃�'},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'tableHeader',
+      label: '琛ㄥご',
+      initval: wrap.tableHeader || 'show',
+      required: false,
+      options: [
+        {value: 'show', label: '鏄剧ず'},
+        {value: 'hidden', label: '闅愯棌'},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'collapse',
+      label: '鍙敹璧�',
+      initval: wrap.collapse || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鏄�'},
+        {value: 'false', label: '鍚�'},
+      ],
+      forbid: appType === 'mob' || appType === 'pc'
+    },
+    {
+      type: 'radio',
+      field: 'size',
+      label: '琛ㄦ牸澶у皬',
+      initval: wrap.size || 'middle',
+      tooltip: '琛ㄦ牸鐨勫唴杈硅窛锛屼粠澶у埌灏忎緷娆¢�掑噺銆�',
+      required: false,
+      options: [
+        {value: 'default', label: '澶�'},
+        {value: 'middle', label: '涓�'},
+        {value: 'small', label: '灏�'},
+        {value: 'mini', label: '杩蜂綘'},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'mode',
+      label: '妯″紡',
+      initval: wrap.mode || 'default',
+      required: false,
+      options: [
+        {value: 'default', label: '甯歌'},
+        {value: 'ghost', label: '閫忔槑'},
+      ]
+    },
+    {
+      type: 'radio',
+      field: 'selected',
+      label: '棣栬閫変腑',
+      initval: wrap.selected || 'false',
+      tooltip: '褰撴寜閽墽琛屽畬鎴愬苟杩斿洖涓婚敭鍊兼椂锛岄粯璁ら�変腑涓婚敭鍊煎搴旇銆�',
+      required: false,
+      options: [
+        {value: 'false', label: '鏃�'},
+        {value: 'init', label: '鍒濆鍖�'},
+        {value: 'always', label: '鏁版嵁鍔犺浇'},
+      ]
+    },
+    // {
+    //   type: 'radio',
+    //   field: 'show',
+    //   label: '鎼滅储鎸夐挳',
+    //   initval: wrap.show || 'true',
+    //   tooltip: '鎼滅储鏉′欢瀛樺湪鏃讹紝鍙�夋嫨鏄惁鏄剧ず鎼滅储鎸夐挳銆�',
+    //   required: false,
+    //   options: [
+    //     {value: 'true', label: '鏄剧ず'},
+    //     {value: 'false', label: '闅愯棌'},
+    //   ]
+    // },
+    {
+      type: 'color',
+      field: 'borderColor',
+      label: '杈规棰滆壊',
+      initval: wrap.borderColor || '#e8e8e8',
+      tooltip: '榛樿鍊� #e8e8e8銆�',
+      required: false
+    },
+    // {
+    //   type: 'color',
+    //   field: 'color',
+    //   label: '瀛椾綋棰滆壊',
+    //   initval: wrap.color || 'rgba(0, 0, 0, 0.65)',
+    //   tooltip: '榛樿鍊� rgba(0, 0, 0, 0.65)銆�',
+    //   required: false
+    // },
+    // {
+    //   type: 'number',
+    //   field: 'fontSize',
+    //   label: '瀛椾綋澶у皬',
+    //   initval: wrap.fontSize || 14,
+    //   min: 12,
+    //   max: 30,
+    //   precision: 0,
+    //   required: false
+    // },
+    // {
+    //   type: 'number',
+    //   field: 'advanceWidth',
+    //   label: '楂樼骇鎼滅储',
+    //   initval: wrap.advanceWidth || 1000,
+    //   tooltip: '楂樼骇鎼滅储寮圭獥鐨勫搴︼紝娉細褰撳搴﹀�煎皬浜�100鏃惰〃绀哄崰绐楀彛鐨勭櫨鍒嗘瘮锛屽ぇ浜�100鏃惰〃绀哄搴︾殑缁濆鍊笺��',
+    //   min: 10,
+    //   max: 3000,
+    //   precision: 0,
+    //   required: false,
+    //   forbid: appType === 'mob'
+    // },
+    {
+      type: 'select',
+      field: 'doubleClick',
+      label: '鍙屽嚮浜嬩欢',
+      initval: wrap.doubleClick || '',
+      tooltip: '鍙屽嚮琛ㄦ牸涓锛岃Е鍙戠殑鎸夐挳銆�',
+      required: false,
+      allowClear: true,
+      options: action.map(item => ({value: item.uuid, label: item.label})),
+      forbid: appType === 'mob'
+    },
+    {
+      type: 'select',
+      field: 'controlField',
+      label: '绂佺敤瀛楁',
+      initval: wrap.controlField || '',
+      tooltip: '鐢ㄤ簬鎺у埗琛屾暟鎹槸鍚﹀彲閫夋嫨銆�',
+      required: false,
+      allowClear: true,
+      options: columns,
+      controlFields: [
+        {field: 'controlVal', notNull: true},
+      ]
+    },
+    {
+      type: 'text',
+      field: 'controlVal',
+      label: '绂佺敤鍊�',
+      initval: wrap.controlVal || '',
+      tooltip: '褰撳瓧娈靛�间笌绂佺敤鍊肩浉绛夋椂锛岃鏁版嵁浼氱鐢紝澶氫釜鍊肩敤閫楀彿鍒嗛殧銆�',
+      required: false
+    },
+    {
+      type: 'radio',
+      field: 'empty',
+      label: '绌哄�奸殣钘�',
+      initval: wrap.empty || 'show',
+      tooltip: '褰撴煡璇㈡暟鎹负绌烘椂锛岄殣钘忚缁勪欢銆�',
+      required: false,
+      options: [
+        {value: 'show', label: '鍚�'},
+        {value: 'hidden', label: '鏄�'},
+      ],
+    },
+    {
+      type: 'radio',
+      field: 'supKey',
+      label: '涓婄骇涓婚敭',
+      initval: wrap.supKey || 'true',
+      tooltip: '褰撹缃笂绾х粍浠舵椂锛屼笂绾т富閿�间负绌烘槸鍚﹁繘琛屾暟鎹煡璇€��',
+      required: false,
+      options: [
+        {value: 'true', label: '楠岃瘉'},
+        {value: 'false', label: '蹇界暐'},
+      ],
+    },
+    {
+      type: 'radio',
+      field: 'permission',
+      label: '鏉冮檺楠岃瘉',
+      initval: wrap.permission || 'false',
+      required: false,
+      options: [
+        {value: 'true', label: '鍚敤'},
+        {value: 'false', label: '绂佺敤'},
+      ],
+      forbid: !appType
+    },
+    {
+      type: 'multiselect',
+      field: 'blacklist',
+      label: '榛戝悕鍗�',
+      initval: wrap.blacklist || [],
+      required: false,
+      options: roleList,
+      forbid: !!appType
+    },
+  ]
+
+  return wrapForm
+} 
\ No newline at end of file
diff --git a/src/menu/modalconfig/index.scss b/src/menu/modalconfig/index.scss
index 814f0fc..e0dcc61 100644
--- a/src/menu/modalconfig/index.scss
+++ b/src/menu/modalconfig/index.scss
@@ -55,41 +55,6 @@
         }
       }
     }
-    .tables {
-      .ant-select-selection-selected-value {
-        opacity: 0.4!important;
-      }
-    }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
   }
   .tools::-webkit-scrollbar {
     width: 4px;
diff --git a/src/menu/tableshell/card.jsx b/src/menu/tableshell/card.jsx
new file mode 100644
index 0000000..aa6116e
--- /dev/null
+++ b/src/menu/tableshell/card.jsx
@@ -0,0 +1,56 @@
+import React from 'react'
+import { useDrag, useDrop } from 'react-dnd'
+
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
+const BaseTable = asyncComponent(() => import('@/menu/components/table/base-table'))
+
+const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
+  const originalIndex = findCard(id).index
+  const [{ isDragging }, drag] = useDrag({
+    item: { type: 'menu', id, originalIndex },
+    collect: monitor => ({
+      isDragging: monitor.isDragging(),
+    }),
+  })
+  const [, drop] = useDrop({
+    accept: 'menu',
+    canDrop: () => true,
+    drop: (item) => {
+      const { id: draggedId, originalIndex } = item
+      if (originalIndex === undefined) {
+        item.dropTargetId = id
+      } else if (draggedId) {
+        if (draggedId === id) return
+        const { index: originIndex } = findCard(draggedId)
+
+        if (originIndex === -1) return
+
+        const { index: overIndex } = findCard(id)
+
+        moveCard(draggedId, overIndex)
+      }
+    }
+  })
+
+  let style = { opacity: 1}
+  if (isDragging) {
+    style = { opacity: 0.3}
+  }
+
+  const getCardComponent = () => {
+    if (card.type === 'table') {
+      return (<BaseTable card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'tabs') {
+      return (<AntvTabs tabs={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    }
+  }
+  return (
+    <div className={'ant-col mk-component-card ant-col-' + (card.width || 24)} ref={node => drag(drop(node))} style={style}>
+      {getCardComponent()}
+    </div>
+  )
+}
+export default Card
diff --git a/src/menu/tableshell/index.jsx b/src/menu/tableshell/index.jsx
new file mode 100644
index 0000000..0346d43
--- /dev/null
+++ b/src/menu/tableshell/index.jsx
@@ -0,0 +1,132 @@
+import React, { useState } from 'react'
+import { useDrop } from 'react-dnd'
+import update from 'immutability-helper'
+import { Modal } from 'antd'
+
+import Utils from '@/utils/utils.js'
+import Card from './card'
+import './index.scss'
+
+const { confirm } = Modal
+
+const Container = ({menu, handleList }) => {
+  const [cards, setCards] = useState(menu.components)
+  const moveCard = (id, atIndex) => {
+    const { card, index } = findCard(id)
+    const _cards = update(cards, { $splice: [[index, 1], [atIndex, 0, card]] })
+    handleList({...menu, components: _cards})
+    setCards(_cards)
+  }
+
+  if (menu.components.length > cards.length) {
+    setCards(menu.components)
+  }
+  
+  const findCard = id => {
+    const card = cards.filter(c => `${c.uuid}` === id)[0]
+    return {
+      card,
+      index: cards.indexOf(card),
+    }
+  }
+
+  const updateConfig = (element) => {
+    const _cards = cards.map(item => item.uuid === element.uuid ? element : item)
+    handleList({...menu, components: _cards})
+    setCards(_cards)
+  }
+
+  const deleteCard = (id) => {
+    const { card } = findCard(id)
+
+    let hasComponent = false
+    if (card.type === 'tabs') {
+      card.subtabs.forEach(tab => {
+        if (tab.components.length > 0) {
+          hasComponent = true
+        }
+      })
+    }
+
+    confirm({
+      title: `纭畾鍒犻櫎銆�${card.name}銆嬪悧锛焋,
+      content: hasComponent ? '褰撳墠缁勪欢涓惈鏈夊瓙缁勪欢锛�' : '',
+      onOk() {
+        const _cards = cards.filter(item => item.uuid !== card.uuid)
+        handleList({...menu, components: _cards})
+        setCards(_cards)
+      },
+      onCancel() {}
+    })
+  }
+
+  const [, drop] = useDrop({
+    accept: 'menu',
+    drop(item) {
+      if (item.hasOwnProperty('originalIndex') || item.added) {
+        delete item.added // 鍒犻櫎缁勪欢娣诲姞鏍囪
+        return
+      }
+
+      let name = ''
+      let names = {
+        tabs: '鏍囩缁�'
+      }
+      let i = 1
+      
+      while (!name && names[item.component]) {
+        let _name = names[item.component] + i
+        if (menu.components.filter(com => com.name === _name).length === 0) {
+          name = _name
+        }
+        i++
+      }
+
+      let newcard = {
+        uuid: Utils.getuuid(),
+        type: item.component,
+        subtype: item.subtype,
+        config: item.config,
+        width: item.width || 24,
+        dataName: Utils.getdataName(),
+        name: name,
+        floor: 1,   // 缁勪欢鐨勫眰绾�
+        isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
+      }
+      
+      let targetId = ''
+
+      if (item.dropTargetId) {
+        targetId = item.dropTargetId
+        delete item.dropTargetId
+      } else if (cards.length > 0) {
+        targetId = cards.slice(-1)[0].uuid
+      }
+
+      const { index: overIndex } = findCard(`${targetId}`)
+      const _cards = update(cards, { $splice: [[overIndex + 1, 0, newcard]] })
+
+      handleList({...menu, components: _cards})
+      setCards(_cards)
+    }
+  })
+
+  return (
+    <div ref={drop} className="table-shell-inner" style={menu.style}>
+      <div className="ant-row">
+        {cards.map(card => (
+          <Card
+            id={card.uuid}
+            key={card.uuid}
+            card={card}
+            moveCard={moveCard}
+            delCard={deleteCard}
+            findCard={findCard}
+            updateConfig={updateConfig}
+          />
+        ))}
+      </div>
+    </div>
+  )
+}
+export default Container
diff --git a/src/menu/tableshell/index.scss b/src/menu/tableshell/index.scss
new file mode 100644
index 0000000..700e55d
--- /dev/null
+++ b/src/menu/tableshell/index.scss
@@ -0,0 +1,21 @@
+.table-shell-inner {
+  min-height: calc(100vh - 100px);
+  width: auto!important;
+  overflow-x: hidden;
+  background-size: 100%;
+
+  .anticon {
+    cursor: unset;
+  }
+
+  .mk-component-card {
+    position: relative;
+  }
+
+  .anticon-tool {
+    color: rgba(0, 0, 0, 0.55);
+  }
+  .anticon-tool:hover {
+    color: #1890ff;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/modalconfig/index.scss b/src/mob/modalconfig/index.scss
index d9c2725..d4fbaa9 100644
--- a/src/mob/modalconfig/index.scss
+++ b/src/mob/modalconfig/index.scss
@@ -57,41 +57,6 @@
         }
       }
     }
-    .tables {
-      .ant-select-selection-selected-value {
-        opacity: 0.4!important;
-      }
-    }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
   }
   .tools::-webkit-scrollbar {
     width: 4px;
diff --git a/src/mob/searchconfig/index.scss b/src/mob/searchconfig/index.scss
index 9eb6275..de9d1a3 100644
--- a/src/mob/searchconfig/index.scss
+++ b/src/mob/searchconfig/index.scss
@@ -20,12 +20,7 @@
     .ant-collapse-borderless {
       background-color: #ffffff;
     }
-    .ant-collapse-item {
-      border: 0;
-    }
-    .ant-input-search {
-      margin-top: 10px;
-    }
+
     .ant-collapse-item.ant-collapse-item-active {
       border-bottom: 1px solid #d9d9d9;
     }
@@ -57,56 +52,8 @@
         }
       }
     }
-    .tables {
-      .ant-select-selection-selected-value {
-        opacity: 0.4!important;
-      }
-    }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
   }
-  .tools::-webkit-scrollbar {
-    width: 4px;
-  }
-  .tools::-webkit-scrollbar-thumb {
-    border-radius: 5px;
-    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.08);
-    background: rgba(0, 0, 0, 0.08);
-  }
-  .tools::-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);
-  }
+
   .modal-control {
     position: absolute;
     right: 0;
@@ -343,7 +290,6 @@
     background: rgba(0, 0, 0, 0);
   }
 }
-
 
 .modal-fields {
   .ant-modal {
diff --git a/src/templates/calendarconfig/index.scss b/src/templates/calendarconfig/index.scss
index a03c742..d40120f 100644
--- a/src/templates/calendarconfig/index.scss
+++ b/src/templates/calendarconfig/index.scss
@@ -54,37 +54,6 @@
       }
     }
     
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        min-height: 55px;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
     .config-button {
       min-width: 65px;
     }
diff --git a/src/templates/comtableconfig/index.scss b/src/templates/comtableconfig/index.scss
index fc49fea..4eb1f51 100644
--- a/src/templates/comtableconfig/index.scss
+++ b/src/templates/comtableconfig/index.scss
@@ -74,37 +74,6 @@
         }
       }
     }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        min-height: 55px;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
     .config-button {
       min-width: 65px;
     }
diff --git a/src/templates/formtabconfig/index.jsx b/src/templates/formtabconfig/index.jsx
index fd2e37b..c01acf3 100644
--- a/src/templates/formtabconfig/index.jsx
+++ b/src/templates/formtabconfig/index.jsx
@@ -5,8 +5,8 @@
 import { DndProvider } from 'react-dnd'
 import HTML5Backend from 'react-dnd-html5-backend'
 import moment from 'moment'
-import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Empty, Switch, Tooltip } from 'antd'
-import { QuestionCircleOutlined, CloseOutlined, RedoOutlined, SettingOutlined, PlusOutlined, DeleteOutlined, EditOutlined, SnippetsOutlined } from '@ant-design/icons'
+import { Button, Card, Modal, Collapse, notification, Spin, Switch, Tooltip } from 'antd'
+import { QuestionCircleOutlined, RedoOutlined, SettingOutlined, PlusOutlined, DeleteOutlined, EditOutlined, SnippetsOutlined } from '@ant-design/icons'
 
 import Api from '@/api'
 import zhCN from '@/locales/zh-CN/model.js'
@@ -22,7 +22,6 @@
 import SettingForm from './settingform'
 import DragElement from './dragelement'
 import GroupForm from './groupform'
-import EditCard from '@/templates/zshare/editcard'
 
 import MenuForm from '@/templates/zshare/menuform'
 import SourceElement from '@/templates/zshare/dragsource'
@@ -31,7 +30,6 @@
 import './index.scss'
 
 const { Panel } = Collapse
-const { Option } = Select
 const { confirm } = Modal
 const ModalForm = asyncComponent(() => import('@/templates/zshare/modalform'))
 const CreateFunc = asyncComponent(() => import('@/templates/zshare/createfunc'))
@@ -49,7 +47,6 @@
     dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,        // 瀛楀吀
     config: null,            // 椤甸潰閰嶇疆
     modaltype: '',           // 妯℃�佹绫诲瀷锛屾帶鍒舵ā鎬佹鏄剧ず
-    tableVisible: false,     // 鏁版嵁琛ㄥ瓧娈垫ā鎬佹
     tableColumns: [],        // 琛ㄦ牸鏄剧ず鍒�
     fields: null,            // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
     menuformlist: null,      // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
@@ -61,7 +58,6 @@
     settingVisible: false,   // 鍏ㄥ眬閰嶇疆妯℃�佹
     closeVisible: false,     // 鍏抽棴妯℃�佹
     tables: [],              // 鍙敤琛ㄥ悕
-    selectedTables: [],      // 宸查�夎〃鍚�
     originMenu: null,        // 鍘熷鑿滃崟
     delActions: [],          // 鍒犻櫎鎸夐挳鍒楄〃
     tabviews: [],            // 鎵�鏈夋爣绛鹃〉
@@ -143,7 +139,6 @@
       openEdition: btnTab.open_edition || '',
       columns: columns,
       originMenu: JSON.parse(JSON.stringify(_config)),
-      selectedTables: _config.tables,
       menuformlist: [
         {
           type: 'text',
@@ -195,73 +190,6 @@
           duration: 5
         })
       }
-    })
-
-    let deffers = this.state.selectedTables.map(item => {
-      return new Promise(resolve => {
-        Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: item.TbName}).then(res => {
-          res.TBName = item.TbName
-          resolve(res)
-        })
-      })
-    })
-    Promise.all(deffers).then(response => {
-      let _columns = []
-      response.forEach(res => {
-        if (res.status) {
-          let tabmsg = {
-            tableName: res.TBName,
-            columns: res.FDName.map(item => {
-              let _type = item.FieldType.toLowerCase()
-              let _decimal = 0
-              if (/^nvarchar/.test(_type)) {
-                _type = 'text'
-              } else if (/^int/.test(_type)) {
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                if (_decimal > 4) {
-                  _decimal = 4
-                }
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                if (_decimal > 4) {
-                  _decimal = 4
-                }
-                _type = 'number'
-              } else if (/^datetime/.test(_type)) {
-                _type = 'datetime'
-              } else if (/^date/.test(_type)) {
-                _type = 'date'
-              } else {
-                _type = 'text'
-              }
-  
-              return {
-                field: item.FieldName,
-                label: item.FieldDec,
-                type: _type,
-                datatype: _type,
-                decimal: _decimal
-              }
-            })
-          }
-          _columns.push(tabmsg)
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-
-      this.setState({
-        tableColumns: _columns
-      })
     })
 
     Api.getSystemConfig({func: 'sPC_Get_UserTemp', TypeCharTwo: 'tab'}).then(res => {
@@ -856,7 +784,7 @@
       }
 
       let _LongParam = ''
-      let _config = {...config, tables: this.state.selectedTables}
+      let _config = {...config}
 
       // 鏁版嵁鏉ユ簮涓烘煡璇笖鏈缃富閿椂锛屽惎鐢ㄤ负false
       if (_config.setting.datatype === 'query' && !_config.setting.primaryKey) {
@@ -1227,7 +1155,7 @@
         onCancel() {}
       })
     } else {
-      let _config = {...config, tables: this.state.selectedTables}
+      let _config = {...config}
 
       if (!is(fromJS(_config), fromJS(originMenu))) {
         this.setState({
@@ -1237,174 +1165,6 @@
         this.handleViewBack()
       }
     }
-  }
-
-  queryField = (type) => {
-    const {selectedTables, tableColumns, config} = this.state
-    // 鍒ゆ柇鏄惁宸查�夋嫨琛ㄥ悕
-    if (selectedTables.length === 0) {
-      notification.warning({
-        top: 92,
-        message: '璇烽�夋嫨琛ㄥ悕锛�',
-        duration: 5
-      })
-      return
-    }
-
-    // 琛ㄥ瓧娈甸泦杞负map鏁版嵁
-    let columns = new Map()
-    tableColumns.forEach(table => {
-      table.columns.forEach(column => {
-        columns.set(column.field, column)
-      })
-    })
-
-    if (type === 'search') {
-      // 娣诲姞鎼滅储鏉′欢锛屽瓧娈甸泦涓瓨鍦ㄦ悳绱㈡潯浠跺瓧娈碉紝浣跨敤鎼滅储鏉′欢瀵硅薄鏇挎崲瀛楁闆嗭紝璁剧疆鏁版嵁绫诲瀷
-      config.groups.forEach(group => {
-        group.sublist.forEach(item => {
-          if (columns.has(item.field)) {
-            let _datatype = columns.get(item.field).datatype
-            columns.set(item.field, {...item, selected: true, datatype: _datatype})
-          }
-        })
-      })
-    }
-
-    // 鏄剧ず瀛楁闆嗗脊绐�
-    this.setState({
-      tableVisible: true,
-      fields: [...columns.values()]
-    })
-  }
-
-  addFieldSubmit = () => {
-    const {config} = this.state
-    // 瀛楁闆嗕负绌猴紝鍏抽棴寮圭獥
-    if (!this.state.fields || this.state.fields.length === 0) {
-      this.setState({
-        tableVisible: false,
-      })
-    }
-
-    // 鑾峰彇宸查�夊瓧娈甸泦鍚�
-    let cards = this.refs.searchcard.state.selectCards
-    let columnsMap = new Map()
-    cards.forEach(card => {
-      columnsMap.set(card.field, card)
-    })
-
-    let groups = config.groups.map(group => {
-      group.sublist = group.sublist.map(item => {
-        if (columnsMap.has(item.field)) {
-          let cell = columnsMap.get(item.field)
-  
-          if (cell.selected && cell.type !== item.type) { // 鏁版嵁绫诲瀷淇敼
-            item.type = cell.type
-            item.initval = ''
-          }
-          columnsMap.delete(item.field)
-        }
-        return item
-      })
-      return group
-    })
-
-    let items =  [...columnsMap.values()].map(item => {
-      let newcard = {
-        uuid: Utils.getuuid(),
-        label: item.label,
-        field: item.field,
-        initval: '',
-        type: item.type,
-        resourceType: '0',
-        options: [],
-        orderType: 'asc'
-      }
-
-      return newcard
-    })
-
-    groups = groups.map(group => {
-      if (group.isDefault) {
-        group.sublist = [...group.sublist, ...items]
-        group.sublist = group.sublist.filter(item => !item.origin)
-      }
-      return group
-    })
-
-    this.setState({
-      config: {...config, groups: groups}
-    })
-    notification.success({
-      top: 92,
-      message: '鎿嶄綔鎴愬姛',
-      duration: 2
-    })
-  }
-
-  onTableChange = (value) => {
-    const {tables, selectedTables, tableColumns} = this.state
-
-    let _table = tables.filter(item => item.TbName === value)[0]
-    let isSelected = !!selectedTables.filter(cell => cell.TbName === value)[0]
-    if (!isSelected) {
-      this.setState({
-        selectedTables: [...selectedTables, _table]
-      })
-      Api.getSystemConfig({func: 'sPC_Get_FieldName', TBName: value}).then(res => {
-        if (res.status) {
-          let tabmsg = {
-            tableName: _table.name,
-            columns: res.FDName.map(item => {
-              let _type = item.FieldType.toLowerCase()
-              let _decimal = 0
-              if (/^nvarchar/.test(_type)) {
-                _type = 'text'
-              } else if (/^int/.test(_type)) {
-                _type = 'number'
-              } else if (/^decimal/.test(_type)) {
-                _decimal = _type.split(',')[1]
-                _decimal = parseInt(_decimal)
-                _type = 'number'
-              } else if (/^datetime/.test(_type)) {
-                _type = 'datetime'
-              } else if (/^date/.test(_type)) {
-                _type = 'date'
-              } else {
-                _type = 'text'
-              }
-
-              return {
-                field: item.FieldName,
-                label: item.FieldDec,
-                type: _type,
-                datatype: _type,
-                decimal: _decimal
-              }
-            })
-          }
-          this.setState({
-            tableColumns: [...tableColumns, tabmsg]
-          })
-        } else {
-          notification.warning({
-            top: 92,
-            message: res.message,
-            duration: 5
-          })
-        }
-      })
-    }
-  }
-
-  deleteTable = (table) => {
-    const {selectedTables, tableColumns} = this.state
-
-    this.setState({
-      selectedTables: selectedTables.filter(item => item.TbName !== table.TbName),
-      tableColumns: tableColumns.filter(item => item.tableName !== table.TbName)
-    })
   }
 
   changeSetting = () => {
@@ -1493,7 +1253,7 @@
       })
     } else {
       this.menuformRef.handleConfirm().then(res => {
-        let _config = {...config, tables: this.state.selectedTables}
+        let _config = {...config}
 
         if (!is(fromJS(originMenu), fromJS(_config))) {
           notification.warning({
@@ -1778,43 +1538,6 @@
                   formlist={this.state.menuformlist}
                   wrappedComponentRef={(inst) => this.menuformRef = inst}
                 />
-                {/* 琛ㄥ悕娣诲姞 */}
-                <div className="ant-col ant-form-item-label">
-                  <label>
-                    <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽湪娣诲姞鎼滅储鏉′欢鍜屾樉绀哄垪鏃讹紝鍙�氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鎵归噺娣诲姞琛ㄦ牸鐩稿叧瀛楁銆�">
-                      <QuestionCircleOutlined className="mk-form-tip" />
-                      {this.state.dict['header.menu.table.add']}
-                    </Tooltip>
-                  </label>
-                </div>
-                <Select
-                  showSearch
-                  className="tables"
-                  style={{ width: '100%' }}
-                  optionFilterProp="children"
-                  value="璇烽�夋嫨琛ㄥ悕"
-                  onChange={this.onTableChange}
-                  showArrow={false}
-                  getPopupContainer={() => document.getElementById('common-basedata')}
-                  filterOption={(input, option) => {
-                    return option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 ||
-                      option.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                  }}
-                > 
-                  {this.state.tables.map((table, index) => (
-                    <Option key={index} title={table.TbName} value={table.TbName}>{table.Remark}</Option>
-                  ))}
-                </Select>
-                {this.state.selectedTables.length > 0 && <List
-                  size="small"
-                  bordered
-                  dataSource={this.state.selectedTables}
-                  renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
-                    {item.Remark + ' (' + item.TbName + ')'}
-                    <CloseOutlined onClick={() => this.deleteTable(item)}/>
-                    <div className="bottom-mask"></div>
-                  </List.Item>}
-                />}
               </Panel>
               {/* 鎼滅储鏉′欢娣诲姞 */}
               <Panel header={this.state.dict['header.menu.form']} key="1">
@@ -1823,7 +1546,6 @@
                     return (<SourceElement key={index} content={item}/>)
                   })}
                 </div>
-                <Button type="primary" block onClick={() => this.queryField('search')}>鎵归噺娣诲姞</Button>
               </Panel>
               {/* 鎸夐挳娣诲姞 */}
               <Panel header={this.state.dict['header.menu.action']} key="2">
@@ -1974,29 +1696,6 @@
             inputSubmit={this.handleSubmit}
             wrappedComponentRef={(inst) => this.actionFormRef = inst}
           />
-        </Modal>
-        {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
-        <Modal
-          wrapClassName="common-table-fields-modal"
-          title={this.state.dict['model.edit']}
-          visible={this.state.tableVisible}
-          width={'65vw'}
-          maskClosable={false}
-          cancelText={this.state.dict['model.close']}
-          onOk={this.addFieldSubmit}
-          onCancel={() => { // 鍙栨秷娣诲姞
-            this.setState({
-              tableVisible: false
-            })
-          }}
-          destroyOnClose
-        >
-          {this.state.fields && this.state.fields.length > 0 ?
-            <EditCard data={this.state.fields} ref="searchcard" type={'form'} dict={this.state.dict} /> : null
-          }
-          {(!this.state.fields || this.state.fields.length === 0) &&
-            <Empty />
-          }
         </Modal>
         {/* 鎸夐挳浣跨敤绯荤粺瀛樺偍杩囩▼鏃讹紝楠岃瘉淇℃伅妯℃�佹 */}
         <Modal
diff --git a/src/templates/formtabconfig/index.scss b/src/templates/formtabconfig/index.scss
index dc1d5ad..d555524 100644
--- a/src/templates/formtabconfig/index.scss
+++ b/src/templates/formtabconfig/index.scss
@@ -59,41 +59,6 @@
       color: #1890ff;
       border-bottom: 1px solid #e8e8e8;
     }
-    .tables {
-      .ant-select-selection-selected-value {
-        opacity: 0.4!important;
-      }
-    }
-    .ant-list {
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        min-height: 55px;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
     .config-button {
       min-width: 65px;
     }
diff --git a/src/templates/modalconfig/index.scss b/src/templates/modalconfig/index.scss
index dfa0948..9325eb1 100644
--- a/src/templates/modalconfig/index.scss
+++ b/src/templates/modalconfig/index.scss
@@ -55,41 +55,6 @@
         }
       }
     }
-    .tables {
-      .ant-select-selection-selected-value {
-        opacity: 0.4!important;
-      }
-    }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
   }
   .tools::-webkit-scrollbar {
     width: 4px;
diff --git a/src/templates/sharecomponent/tablecomponent/index.jsx b/src/templates/sharecomponent/tablecomponent/index.jsx
index f2da2b6..5a084df 100644
--- a/src/templates/sharecomponent/tablecomponent/index.jsx
+++ b/src/templates/sharecomponent/tablecomponent/index.jsx
@@ -8,8 +8,6 @@
 import Api from '@/api'
 import options from '@/store/options.js'
 import Utils from '@/utils/utils.js'
-import zhCN from '@/locales/zh-CN/model.js'
-import enUS from '@/locales/en-US/model.js'
 import { queryTableSql } from '@/utils/option.js'
 
 import './index.scss'
@@ -24,7 +22,6 @@
   }
 
   state = {
-    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     tables: [],          // 绯荤粺琛�
     tableFields: [],     // 宸查�夎〃瀛楁闆�
     selectedTables: [],  // 宸查�夎〃
@@ -268,16 +265,16 @@
 
   render() {
     const { containerId } = this.props
-    const { dict, tables, selectedTables } = this.state
+    const { tables, selectedTables } = this.state
 
     return (
-      <div className="model-table-tablemanage-view">
+      <div className="model-tablename-manage-view">
         {/* 琛ㄥ悕娣诲姞 */}
         <div className="ant-col ant-form-item-label">
           <label>
             <Tooltip placement="topLeft" title="姝ゅ鍙互娣诲姞椤甸潰閰嶇疆鐩稿叧鐨勫父鐢ㄨ〃锛屽彲閫氳繃宸ュ叿鏍忎腑鐨勬坊鍔犳寜閽紝鍙壒閲忔坊鍔犺〃鏍肩浉鍏冲瓧娈点��">
               <QuestionCircleOutlined className="mk-form-tip" />
-              {dict['header.menu.table.add']}
+              琛ㄥ悕
             </Tooltip>
           </label>
         </div>
@@ -307,7 +304,6 @@
           renderItem={(item, index) => <List.Item key={index} title={item.Remark + ' (' + item.TbName + ')'}>
             {item.Remark + ' (' + item.TbName + ')'}
             <CloseOutlined onClick={() => this.deleteTable(item)}/>
-            <div className="bottom-mask"></div>
           </List.Item>}
         />}
       </div>
diff --git a/src/templates/sharecomponent/tablecomponent/index.scss b/src/templates/sharecomponent/tablecomponent/index.scss
index aa254b7..407a9e9 100644
--- a/src/templates/sharecomponent/tablecomponent/index.scss
+++ b/src/templates/sharecomponent/tablecomponent/index.scss
@@ -1,7 +1,33 @@
-.model-table-tablemanage-view {
+.model-tablename-manage-view {
+  >.ant-list {
+    margin-top: 20px;
+    .ant-list-item {
+      display: -webkit-box;
+      padding-right: 20px;
+      position: relative;
+      padding-left: 5px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      min-height: 55px;
+      width: 100%;
+      .anticon {
+        position: absolute;
+        top: 0px;
+        right: 0px;
+        padding: 3px 3px 10px 10px;
+        cursor: pointer;
+      }
+    }
+  }
   .tables {
+    width: 66.66666667%!important;
     .ant-select-selection-selected-value {
       opacity: 0.4!important;
     }
   }
+  >.ant-form-item-label {
+    width: 33.33333333%;
+  }
 }
\ No newline at end of file
diff --git a/src/templates/subtableconfig/index.scss b/src/templates/subtableconfig/index.scss
index 0adcbba..4f91d6e 100644
--- a/src/templates/subtableconfig/index.scss
+++ b/src/templates/subtableconfig/index.scss
@@ -63,37 +63,6 @@
         border-bottom: 1px solid #e8e8e8;
       }
     }
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        min-height: 55px;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
     .config-button {
       min-width: 65px;
     }
diff --git a/src/templates/treepageconfig/index.scss b/src/templates/treepageconfig/index.scss
index 2ee9942..b998125 100644
--- a/src/templates/treepageconfig/index.scss
+++ b/src/templates/treepageconfig/index.scss
@@ -53,38 +53,6 @@
         }
       }
     }
-    
-    .ant-list {
-      margin-top: 20px;
-      .ant-list-item {
-        display: -webkit-box;
-        padding-right: 20px;
-        position: relative;
-        padding-left: 5px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-        min-height: 55px;
-        width: 100%;
-        .anticon {
-          position: absolute;
-          top: 0px;
-          right: 0px;
-          padding: 3px 3px 10px 10px;
-          cursor: pointer;
-        }
-        .bottom-mask {
-          position: absolute;
-          width: 100%;
-          height: 8px;
-          bottom: 0;
-          left: 0;
-          background: #ffffff;
-          border-radius: 8px;
-        }
-      }
-    }
     .config-button {
       min-width: 65px;
     }
diff --git a/src/views/imdesign/index.scss b/src/views/imdesign/index.scss
index 2ad3e4b..8f951be 100644
--- a/src/views/imdesign/index.scss
+++ b/src/views/imdesign/index.scss
@@ -61,36 +61,6 @@
           .ant-form-item {
             margin-bottom: 10px;
           }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
-          }
         }
       }
   
diff --git a/src/views/menudesign/index.scss b/src/views/menudesign/index.scss
index ceeac78..6e9f063 100644
--- a/src/views/menudesign/index.scss
+++ b/src/views/menudesign/index.scss
@@ -102,36 +102,6 @@
           .ant-form-item {
             margin-bottom: 10px;
           }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
-          }
         }
       }
 
diff --git a/src/views/mobdesign/index.scss b/src/views/mobdesign/index.scss
index 273160d..0dfd9d5 100644
--- a/src/views/mobdesign/index.scss
+++ b/src/views/mobdesign/index.scss
@@ -108,36 +108,6 @@
           .ant-form-item {
             margin-bottom: 10px;
           }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
-          }
         }
       }
   
@@ -308,7 +278,7 @@
           display: block;
         }
       }
-      .url-field-component, .model-table-tablemanage-view, .ant-typography {
+      .url-field-component, .model-tablename-manage-view, .ant-typography {
         display: none;
       }
     }
diff --git a/src/views/pcdesign/index.scss b/src/views/pcdesign/index.scss
index 60a0d03..881e06c 100644
--- a/src/views/pcdesign/index.scss
+++ b/src/views/pcdesign/index.scss
@@ -113,36 +113,6 @@
           .ant-form-item {
             margin-bottom: 10px;
           }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
-          }
         }
       }
   
diff --git a/src/views/popdesign/index.scss b/src/views/popdesign/index.scss
index 416bbb5..2d06a62 100644
--- a/src/views/popdesign/index.scss
+++ b/src/views/popdesign/index.scss
@@ -78,36 +78,6 @@
           .ant-form-item {
             margin-bottom: 10px;
           }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
-          }
         }
       }
 
diff --git a/src/views/tabledesign/index.jsx b/src/views/tabledesign/index.jsx
index 22235cd..72f85d8 100644
--- a/src/views/tabledesign/index.jsx
+++ b/src/views/tabledesign/index.jsx
@@ -22,7 +22,7 @@
 
 const MenuForm = asyncComponent(() => import('./menuform'))
 const Header = asyncComponent(() => import('@/menu/header'))
-const MenuShell = asyncComponent(() => import('@/menu/menushell'))
+const MenuShell = asyncComponent(() => import('@/menu/tableshell'))
 const BgController = asyncComponent(() => import('@/pc/bgcontroller'))
 const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
 const ReplaceField = asyncComponent(() => import('@/menu/replaceField'))
@@ -43,7 +43,6 @@
     ParentId: '',
     MenuName: '',
     MenuNo: '',
-    delButtons: [],
     activeKey: 'basedata',
     menuloading: false,
     oriConfig: null,
@@ -87,7 +86,6 @@
   }
 
   componentDidMount () {
-    MKEmitter.addListener('delButtons', this.delButtons)
     MKEmitter.addListener('modalStatus', this.modalStatus)
     MKEmitter.addListener('changePopview', this.initPopview)
     MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
@@ -156,7 +154,6 @@
     this.setState = () => {
       return
     }
-    MKEmitter.removeListener('delButtons', this.delButtons)
     MKEmitter.removeListener('modalStatus', this.modalStatus)
     MKEmitter.removeListener('changePopview', this.initPopview)
     MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
@@ -325,10 +322,6 @@
     })
   }
 
-  delButtons = (items) => {
-    this.setState({ delButtons: [...this.state.delButtons, ...items] })
-  }
-
   initPopview = (card, btn) => {
     const { oriConfig, config } = this.state
 
@@ -401,7 +394,42 @@
             MenuName: MenuName,
             MenuNo: MenuNo,
             tables: [],
-            components: [],
+            components: [
+              {
+                uuid: Utils.getuuid(),
+                type: 'table',
+                tabId: '',
+                parentId: '',
+                format: 'array',    // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
+                pageable: true,     // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
+                switchable: true,   // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
+                dataName: '',
+                width: 24,
+                search: [
+                  { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'text', match: 'like' },
+                  { origin: true, uuid: Utils.getuuid(), label: 'label', field: '', type: 'select', match: 'equal' }
+                ],
+                action: [
+                  { origin: true, uuid: Utils.getuuid(), label: '娣诲姞', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'plus', class: 'green', style: {color: 'rgb(255, 255, 255)', background: 'rgb(38, 194, 129)', marginRight: '15px'} },
+                  { origin: true, uuid: Utils.getuuid(), label: '淇敼', intertype: 'system', OpenType: 'pop', execSuccess: 'grid', icon: 'form', class: 'purple', style: {color: 'rgb(255, 255, 255)', background: 'rgb(142, 68, 173)', marginRight: '15px'} },
+                  { origin: true, uuid: Utils.getuuid(), label: '鍒犻櫎', intertype: 'system', OpenType: 'prompt', execSuccess: 'grid', Ot: 'required', icon: 'delete', class: 'danger', style: {color: 'rgb(255, 255, 255)', background: 'rgb(255, 77, 79)', marginRight: '15px'} }
+                ],
+                name: '涓昏〃',
+                subtype: 'basetable',
+                setting: { interType: 'system' },
+                wrap: {},
+                style: {},
+                headerStyle: {},
+                columns: [],
+                cols: [
+                  { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label1', field: '', Hide: 'false', type: 'text', Width: 120 },
+                  { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label2', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+                  { origin: true, uuid: Utils.getuuid(), Align: 'left', label: 'label3', field: '', Hide: 'false', IsSort: 'true', type: 'text', Width: 120 },
+                ],
+                scripts: [],
+                isNew: true
+              }
+            ],
             viewType: 'menu',
             style: {
               backgroundColor: '#ffffff', backgroundImage: '',
@@ -587,7 +615,7 @@
         LText: []
       }
 
-      let delButtons = fromJS(this.state.delButtons).toJS()
+      let delButtons = []
 
       btnParam.LText = this.getMenuMessage(delButtons)
       btnParam.LText = btnParam.LText.join(' union all ')
@@ -665,7 +693,6 @@
       }).then(res => {
         if (res && res.status) {
           this.setState({
-            delButtons: [],
             menuloading: false
           })
           notification.success({
diff --git a/src/views/tabledesign/index.scss b/src/views/tabledesign/index.scss
index 2286991..c022ade 100644
--- a/src/views/tabledesign/index.scss
+++ b/src/views/tabledesign/index.scss
@@ -64,7 +64,7 @@
       top: 48px;
       z-index: 10;
       height: calc(100vh - 48px);
-      width: 300px;
+      width: 280px;
       background: #ffffff;
       box-shadow: 0px 2px 5px #bcbcbc;
       transition: left 0.3s;
@@ -99,38 +99,9 @@
           color: #ffffff;
         }
         .ant-collapse-content-box {
+          padding: 10px;
           .ant-form-item {
             margin-bottom: 10px;
-          }
-          .model-table-tablemanage-view {
-            >.ant-list {
-              margin-top: 20px;
-              .ant-list-item {
-                display: -webkit-box;
-                padding-right: 20px;
-                position: relative;
-                padding-left: 5px;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                -webkit-line-clamp: 2;
-                -webkit-box-orient: vertical;
-                min-height: 55px;
-                width: 100%;
-                .anticon {
-                  position: absolute;
-                  top: 0px;
-                  right: 0px;
-                  padding: 3px 3px 10px 10px;
-                  cursor: pointer;
-                }
-              }
-            }
-            >.tables {
-              width: 66.66666667%!important;
-            }
-            >.ant-form-item-label {
-              width: 33.33333333%;
-            }
           }
         }
       }
@@ -175,8 +146,8 @@
 
     .menu-view {
       position: relative;
-      width: calc(100vw - 300px);
-      margin-left: 300px;
+      width: calc(100vw - 280px);
+      margin-left: 280px;
       height: calc(100vh - 50px);
       overflow-y: auto;
       transition: all 0.3s;
diff --git a/src/views/tabledesign/menuform/index.jsx b/src/views/tabledesign/menuform/index.jsx
index 4b68d28..b779db1 100644
--- a/src/views/tabledesign/menuform/index.jsx
+++ b/src/views/tabledesign/menuform/index.jsx
@@ -303,13 +303,6 @@
             </Form.Item>
           </Col>
           <Col span={24}>
-            <Form.Item label="鍔╄鐮�">
-              {getFieldDecorator('easyCode', {
-                initialValue: config.easyCode
-              })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
-            </Form.Item>
-          </Col>
-          <Col span={24}>
             <Form.Item label={'闅愯棌鑿滃崟'}>
               <Switch checkedChildren={'鏄�'} checked={config.hidden === 'true'} unCheckedChildren={'鍚�'} onChange={(value) => {
                 this.selectChange('hidden', value + '')
@@ -317,6 +310,13 @@
             </Form.Item>
           </Col>
           <Col span={24}>
+            <Form.Item label="鍔╄鐮�">
+              {getFieldDecorator('easyCode', {
+                initialValue: config.easyCode
+              })(<Input placeholder="" autoComplete="off" onChange={this.changeEasyCode}/>)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
             <Form.Item label="澶囨敞">
               {getFieldDecorator('Remark', {
                 initialValue: config.Remark || '',

--
Gitblit v1.8.0