From 67e7787f24a1ca3dc45f77fb7bbcb76edc33fe55 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期五, 22 十一月 2019 09:55:52 +0800
Subject: [PATCH] 2019-11-22-01

---
 src/templates/modalconfig/editcard/index.jsx          |    0 
 src/templates/modalconfig/columnform/index.jsx        |    0 
 src/templates/modalconfig/searchform/index.jsx        |    0 
 src/templates/modalconfig/settingform/index.scss      |    0 
 src/templates/comtableconfig/columnform/index.scss    |    0 
 src/templates/comtableconfig/dragelement/itemtypes.js |    0 
 src/templates/modalconfig/dragelement/source.jsx      |    0 
 src/templates/comtableconfig/searchform/index.jsx     |  273 +++++
 src/templates/modalconfig/index.jsx                   |    0 
 src/templates/modalconfig/searchform/index.scss       |    0 
 src/locales/zh-CN/comtable.js                         |    4 
 src/templates/comtableconfig/dragelement/index.jsx    |    0 
 src/templates/modalconfig/dragelement/card.jsx        |    0 
 src/locales/en-US/comtable.js                         |    4 
 src/templates/comtableconfig/dragelement/card.jsx     |   89 +
 src/templates/modalconfig/actionform/index.jsx        |    0 
 src/templates/comtableconfig/editable/index.jsx       |    0 
 src/templates/modalconfig/dragelement/index.scss      |    0 
 src/templates/comtableconfig/menuform/index.scss      |    0 
 src/templates/comtableconfig/editcard/index.scss      |   43 
 src/templates/comtableconfig/columnform/index.jsx     |    0 
 src/templates/comtableconfig/searchform/index.scss    |    0 
 src/templates/comtableconfig/editable/index.scss      |    0 
 src/templates/modalconfig/dragelement/itemtypes.js    |    0 
 src/components/header/index.jsx                       |    4 
 src/templates/modalconfig/editable/index.jsx          |    0 
 src/templates/modalconfig/menuform/index.scss         |    0 
 src/templates/comtableconfig/index.jsx                | 1448 +++++++++++++++++++++++++++
 src/templates/comtableconfig/dragelement/index.scss   |    0 
 src/templates/modalconfig/columnform/index.scss       |    0 
 src/templates/modalconfig/dragelement/index.jsx       |    0 
 src/templates/comtableconfig/editcard/index.jsx       |   99 +
 src/templates/modalconfig/editable/index.scss         |    0 
 src/templates/modalconfig/editcard/index.scss         |    0 
 src/templates/comtableconfig/actionform/index.jsx     |  304 +++++
 src/templates/modalconfig/index.scss                  |    0 
 src/templates/comtableconfig/menuform/index.jsx       |    0 
 src/templates/modalconfig/settingform/index.jsx       |    0 
 src/templates/comtableconfig/source.jsx               |  274 +++++
 src/components/sidemenu/editthdmenu/index.jsx         |  140 --
 src/templates/comtableconfig/settingform/index.jsx    |    0 
 src/templates/comtableconfig/actionform/index.scss    |    7 
 src/utils/asyncLoadComponent.jsx                      |   32 
 src/templates/modalconfig/menuform/index.jsx          |    0 
 src/templates/comtableconfig/index.scss               |  368 +++++++
 src/templates/comtableconfig/dragelement/source.jsx   |    0 
 src/templates/modalconfig/source.jsx                  |    0 
 src/templates/comtableconfig/settingform/index.scss   |    0 
 src/templates/modalconfig/actionform/index.scss       |    0 
 49 files changed, 2,972 insertions(+), 117 deletions(-)

diff --git a/src/components/header/index.jsx b/src/components/header/index.jsx
index 85abdff..069158e 100644
--- a/src/components/header/index.jsx
+++ b/src/components/header/index.jsx
@@ -12,8 +12,8 @@
 import zhCN from '@/locales/zh-CN/header.js'
 import enUS from '@/locales/en-US/header.js'
 import Utils from '@/utils/utils.js'
-import logourl from '../../assets/img/mlogo.png'
-import avatar from '../../assets/img/avatar.jpg'
+import logourl from '@/assets/img/mlogo.png'
+import avatar from '@/assets/img/avatar.jpg'
 import './index.scss'
 
 const EditMenu = asyncComponent(() => import('./editmenu'))
diff --git a/src/components/sidemenu/editthdmenu/index.jsx b/src/components/sidemenu/editthdmenu/index.jsx
index 421da31..53ee91e 100644
--- a/src/components/sidemenu/editthdmenu/index.jsx
+++ b/src/components/sidemenu/editthdmenu/index.jsx
@@ -8,16 +8,15 @@
 import TransferForm from '@/components/transferform'
 import Utils from '@/utils/utils.js'
 import DragElement from '../menuelement'
-// import MenuForm from '../menuform'
-// import ComTableConfig from '../comtableconfig'
-import asyncComponent from '@/utils/asyncComponent'
+import asyncLoadComponent from '@/utils/asyncLoadComponent'
 import Api from '@/api'
 import zhCN from '@/locales/zh-CN/header.js'
 import enUS from '@/locales/en-US/header.js'
 import nortable from '@/assets/img/normaltable.jpg'
 import './index.scss'
 
-const ComTableConfig = asyncComponent(() => import('../comtableconfig'))
+const ComTableConfig = asyncLoadComponent(() => import('@/templates/comtableconfig'))
+const ModalConfig = asyncLoadComponent(() => import('@/templates/modalconfig'))
 const { confirm } = Modal
 const { TabPane } = Tabs
 const illust = {
@@ -43,7 +42,6 @@
     tabview: '', // 閫夋嫨妯℃澘绐楀彛锛坱emplate锛夈�佸熀纭�琛ㄦ牸閰嶇疆锛圕ommonTable锛�
     formlist: null,
     editMenu: null, // 缂栬緫鑿滃崟
-    editMvisible: false, // 缂栬緫鑿滃崟妯℃�佹
     thawMvisible: false, // 瑙i櫎鍐荤粨妯℃�佹
     confirmLoading: false, // 鎻愪氦涓�傘�傘��
     dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
@@ -118,6 +116,7 @@
             }
           }
           _menu.LongParam = _LongParam
+          _menu.ParentID = this.props.supMenu.MenuID
           // console.log(_menu)
           // 妫�娴嬫ā鏉挎槸鍚﹀瓨鍦�
           let _Template = this.state.baseTemplates.filter(temp => temp.type === _menu.PageParam.Template)
@@ -212,14 +211,6 @@
     }
   }
 
-  // memuHandleCancel = () => {
-  //   this.setState({
-  //     editMvisible: false,
-  //     visible: false
-  //   })
-  //   this.resetFormlist()
-  // }
-
   thawMemuSubmit = () => {
     // 涓夌骇鑿滃崟瑙i櫎鍐荤粨
     if (this.refs.trawmenu.state.targetKeys.length === 0) {
@@ -303,7 +294,8 @@
           text: '',
           type: template.type,
           PageParam: {OpenType: "newtab", Template: template.type},
-          LongParam: ''
+          LongParam: '',
+          ParentID: this.props.supMenu.MenuID
         }
       })
     } else {
@@ -316,107 +308,6 @@
     }
     document.getElementById('root').style.overflowY = 'hidden'
   }
-
-  // submitMenuConfig = () => {
-  //   if (this.state.type !== 'edit') {
-  //     this.setState({
-  //       visible: true,
-  //       title: this.state.dict['header.menu.addtitle'],
-  //       formlist: [
-  //         {
-  //           type: 'text',
-  //           key: 'parentId',
-  //           label: this.state.dict['header.menu.supMenu'],
-  //           initVal: this.props.supMenu.text,
-  //           required: true,
-  //           readonly: true
-  //         },
-  //         {
-  //           type: 'text',
-  //           key: 'menuName',
-  //           label: this.state.dict['header.menu.menuName'],
-  //           initVal: '',
-  //           required: true,
-  //           readonly: false
-  //         },
-  //         {
-  //           type: 'text',
-  //           key: 'menuNo',
-  //           label: this.state.dict['header.menu.menuNo'],
-  //           initVal: '',
-  //           required: true,
-  //           readonly: false
-  //         },
-  //         {
-  //           type: 'select',
-  //           key: 'opentype',
-  //           label: '鎵撳紑鏂瑰紡',
-  //           initVal: 'newtab',
-  //           required: true,
-  //           options: [{
-  //             MenuID: 'newtab',
-  //             text: '鏂版爣绛鹃〉'
-  //           }, {
-  //             MenuID: 'newpage',
-  //             text: '鏂伴〉闈�'
-  //           }]
-  //         }
-  //       ]
-  //     })
-  //   } else {
-  //     console.log(this.state.editMenu)
-  //     // confirm({
-  //     //   title: this.state.dict['header.menu.update'].replace('@M', menu.card.text),
-  //     //   content: '',
-  //     //   okText: this.state.dict['header.confirm'],
-  //     //   cancelText: this.state.dict['header.cancel'],
-  //     //   onOk() {
-  //     //     let param = {
-  //     //       func: 'sPC_MainMenu_Del',
-  //     //       MenuID: menu.card.MenuID
-  //     //     }
-  //     //     return Api.getSystemConfig(param).then(res => {
-  //     //       if (res.status) {
-  //     //         _this.props.reload()
-  //     //       } else {
-  //     //         notification.warning({
-  //     //           top: 92,
-  //     //           message: res.message,
-  //     //           duration: 10
-  //     //         })
-  //     //       }
-  //     //     })
-  //     //   },
-  //     //   onCancel() {}
-  //     // })
-  //     this.setState({
-  //       tabview: this.state.selectTemp.type
-  //     })
-  //   }
-  // }
-
-  // changeTemp = () => {
-  //   this.setState({
-  //     editMvisible: false,
-  //     tabview: 'template'
-  //   })
-  //   this.resetFormlist()
-  // }
-
-  // changeConfig = () => {
-  //   this.setState({
-  //     editMvisible: false,
-  //     tabview: this.state.editMenu.PageParam.Template,
-  //     menuConfig: window.atob(this.state.editMenu.LongParam)
-  //   })
-  //   this.resetFormlist()
-  // }
-  
-  // resetFormlist = () => {
-  //   setTimeout(() => {
-  //     this.setState({formlist: null})
-  //   }, 300)
-  // }
 
   getUsedTemplate = () => {
     Api.getSystemConfig({func: 'sPC_Get_UserTemp'}).then(res => {
@@ -449,6 +340,17 @@
   handleConfig = (type) => {
     this.setState({tabview: type})
     document.getElementById('root').style.overflowY = 'unset'
+  }
+
+  handleSubConfig = (item, originMenu, config) => {
+    if (item.OpenType === 'pop') {
+      // this.setState({
+      //   editMenu: originMenu,
+      //   tabview: 'Modal'
+      // })
+    }
+    console.log(item)
+    console.log(originMenu)
   }
 
   UNSAFE_componentWillMount () {
@@ -536,6 +438,14 @@
           <ComTableConfig
             type={this.state.type}
             menu={this.state.editMenu}
+            supMenuList={this.props.supMenuList}
+            handleConfig={this.handleConfig}
+            handleSubConfig={this.handleSubConfig}
+          />
+        }
+        {this.state.tabview === 'Modal' &&
+          <ModalConfig
+            menu={this.state.editMenu}
             supMenu={this.props.supMenu}
             supMenuList={this.props.supMenuList}
             handleConfig={this.handleConfig}
diff --git a/src/locales/en-US/comtable.js b/src/locales/en-US/comtable.js
index 5b1ad4c..7cf9624 100644
--- a/src/locales/en-US/comtable.js
+++ b/src/locales/en-US/comtable.js
@@ -30,6 +30,9 @@
   'header.form.innerFunc': '鍐呴儴鍑芥暟',
   'header.form.outerFunc': '澶栭儴鍑芥暟',
   'header.form.callbackFunc': '鍥炶皟鍑芥暟',
+  'header.form.position': '鏄剧ず浣嶇疆',
+  'header.form.toolbar': '宸ュ叿鏍�',
+  'header.form.grid': '琛ㄦ牸',
   'header.form.intertype': '鎺ュ彛绫诲瀷',
   'header.form.interface': '鎺ュ彛鍦板潃',
   'header.form.interface.inner': '鍐呴儴',
@@ -74,6 +77,7 @@
   'header.form.valueText': '鏂囨湰路瀛楁',
   'header.form.orderBy': '鎺掑簭路瀛楁',
   'header.form.orderType': '鎺掑簭鏂瑰紡',
+  'header.form.match': '鍖归厤妯″紡',
   'header.form.asc': '姝e簭',
   'header.form.desc': '鍊掑簭',
   'header.form.linkField': '鍏宠仈瀛楁',
diff --git a/src/locales/zh-CN/comtable.js b/src/locales/zh-CN/comtable.js
index 47593d8..9e1ae17 100644
--- a/src/locales/zh-CN/comtable.js
+++ b/src/locales/zh-CN/comtable.js
@@ -30,6 +30,9 @@
   'header.form.innerFunc': '鍐呴儴鍑芥暟',
   'header.form.outerFunc': '澶栭儴鍑芥暟',
   'header.form.callbackFunc': '鍥炶皟鍑芥暟',
+  'header.form.position': '鏄剧ず浣嶇疆',
+  'header.form.toolbar': '宸ュ叿鏍�',
+  'header.form.grid': '琛ㄦ牸',
   'header.form.intertype': '鎺ュ彛绫诲瀷',
   'header.form.interface': '鎺ュ彛鍦板潃',
   'header.form.interface.inner': '鍐呴儴',
@@ -74,6 +77,7 @@
   'header.form.valueText': '鏂囨湰路瀛楁',
   'header.form.orderBy': '鎺掑簭路瀛楁',
   'header.form.orderType': '鎺掑簭鏂瑰紡',
+  'header.form.match': '鍖归厤妯″紡',
   'header.form.asc': '姝e簭',
   'header.form.desc': '鍊掑簭',
   'header.form.linkField': '鍏宠仈瀛楁',
diff --git a/src/templates/comtableconfig/actionform/index.jsx b/src/templates/comtableconfig/actionform/index.jsx
new file mode 100644
index 0000000..b327c62
--- /dev/null
+++ b/src/templates/comtableconfig/actionform/index.jsx
@@ -0,0 +1,304 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, Icon, Radio } from 'antd'
+import './index.scss'
+
+const btnIcons = [{
+  MenuID: '',
+  text: 'unset'
+}, {
+  MenuID: 'plus',
+  text: 'plus'
+}, {
+  MenuID: 'plus-circle',
+  text: 'plus-circle'
+}, {
+  MenuID: 'edit',
+  text: 'edit'
+}, {
+  MenuID: 'form',
+  text: 'form'
+}, {
+  MenuID: 'close',
+  text: 'close'
+}, {
+  MenuID: 'close-circle',
+  text: 'close-circle'
+}, {
+  MenuID: 'delete',
+  text: 'delete'
+}]
+
+const btnClasses = [{
+  MenuID: 'default',
+  text: '榛樿锛堥粦杈圭櫧搴曪級'
+}, {
+  MenuID: 'primary',
+  text: '钃濊壊'
+}, {
+  MenuID: 'yellow',
+  text: '榛勮壊'
+}, {
+  MenuID: 'danger',
+  text: '绾㈣壊'
+}, {
+  MenuID: 'green',
+  text: '缁胯壊'
+}, {
+  MenuID: 'dgreen',
+  text: '娣辩豢鑹�'
+}, {
+  MenuID: 'purple',
+  text: '绱壊'
+}, {
+  MenuID: 'gray',
+  text: '鐏拌壊'
+}]
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    formlist: PropTypes.any,
+    card: PropTypes.any
+  }
+
+  state = {
+    formlist: null,
+    openType: null,
+    interType: null,
+    expand: false
+  }
+
+  openTypeChange = (key, value) => {
+    if (key === 'OpenType') {
+      let _options = null
+      if (value === 'newpage') {
+        _options = ['label', 'position', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class']
+      }
+      this.setState({
+        openType: value,
+        expand: value === 'newpage' ? false : this.state.expand,
+        formlist: this.state.formlist.map(item => {
+          if (_options) {
+            item.hidden = !_options.includes(item.key)
+            if (item.key === 'intertype') {
+              item.initVal = 'inner'
+            }
+            item.readonly = ['interface', 'outerFunc', 'callbackFunc'].includes(item.key)
+          }
+          return item
+        })
+      })
+    }
+  }
+
+  onChange = (e, key) => {
+    let value = e.target.value
+    if (key === 'intertype') {
+      this.setState({
+        interType: value,
+        formlist: this.state.formlist.map(item => {
+          if (value === 'inner') {
+            item.readonly = ['interface', 'outerFunc', 'callbackFunc'].includes(item.key)
+          } else {
+            item.readonly = false
+          }
+          return item
+        })
+      })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+    this.state.formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: item.readonly ? false : !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<Input placeholder="" autoComplete="off" disabled={item.readonly} />)}
+            </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[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.openTypeChange(item.key, value)}}
+                  getPopupContainer={() => document.getElementById('winter')}
+                >
+                  {item.options.map(option =>
+                    <Select.Option id={option.MenuID} title={option.text} key={option.MenuID} value={option.MenuID}>
+                      {item.key === 'icon' && option.MenuID && <Icon type={option.MenuID} />} {option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'radio') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
+                  {
+                    item.options.map(option => {
+                      return (
+                        <Radio key={option.MenuID} value={option.MenuID}>{option.text}</Radio>
+                      )
+                    })
+                  }
+                </Radio.Group>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          values.id = this.props.card.id
+          values.uuid = this.props.card.uuid
+          if (!this.state.expand) {
+            values.intertype = 'inner'
+          }
+          resolve({
+            type: 'action',
+            values
+          })
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  toggle = () => {
+    let expand = !this.state.expand
+    let _options = null
+    if (expand) {
+      _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class']
+    } else {
+      _options = ['label', 'position', 'OpenType', 'innerFunc', 'Ot', 'icon', 'class']
+    }
+    if (!expand) {
+      this.setState({
+        expand: !this.state.expand,
+        formlist: this.state.formlist.map(item => {
+          if (item.key === 'intertype') {
+            item.initVal = 'inner'
+          }
+          item.readonly = ['interface', 'outerFunc', 'callbackFunc'].includes(item.key)
+          item.hidden = !_options.includes(item.key)
+          return item
+        })
+      })
+    } else {
+      this.setState({
+        expand: !this.state.expand,
+        formlist: this.state.formlist.map(item => {
+          item.hidden = !_options.includes(item.key)
+          return item
+        })
+      })
+    }
+  }
+
+  UNSAFE_componentWillMount () {
+    let _opentype = this.props.formlist.filter(form => form.key === 'OpenType')[0].initVal
+    let _intertype = this.props.formlist.filter(form => form.key === 'intertype')[0].initVal
+    let _options = null
+    if (_opentype === 'newpage') {
+      _options = ['label', 'Ot', 'OpenType', 'pageTemplate', 'icon', 'class', 'position']
+    } else {
+      if (_intertype === 'outer') {
+      _options = ['label', 'position', 'OpenType', 'intertype', 'innerFunc', 'interface', 'outerFunc', 'callbackFunc', 'Ot', 'icon', 'class']
+      } else {
+        _options = ['label', 'position', 'OpenType', 'innerFunc', 'Ot', 'icon', 'class']
+      }
+    }
+    this.setState({
+      openType: _opentype,
+      interType: _intertype,
+      expand: _intertype === 'outer' ? true : false,
+      formlist: this.props.formlist.map(item => {
+        if (item.key === 'class') {
+          item.options = btnClasses
+        } else if (item.key === 'icon') {
+          item.options = btnIcons
+        }
+        if (_intertype === 'inner') {
+          item.readonly = ['interface', 'outerFunc', 'callbackFunc'].includes(item.key)
+        }
+        item.hidden = !_options.includes(item.key)
+        return item
+      })
+    })
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 7 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 17 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form commontable-action-form" id="winter">
+        <Row gutter={24}>{this.getFields()}</Row>
+        {this.state.openType !== 'newpage' && <Row>
+          <Col span={24} style={{ textAlign: 'right' }}>
+            <span className="superconfig" onClick={this.toggle}>
+              楂樼骇璁剧疆 <Icon type={this.state.expand ? 'up' : 'down'} />
+            </span>
+          </Col>
+        </Row>}
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/templates/comtableconfig/actionform/index.scss b/src/templates/comtableconfig/actionform/index.scss
new file mode 100644
index 0000000..12de954
--- /dev/null
+++ b/src/templates/comtableconfig/actionform/index.scss
@@ -0,0 +1,7 @@
+.ant-advanced-search-form.commontable-action-form {
+  min-height: 190px;
+  .superconfig {
+    color: #1890ff;
+    cursor: pointer;
+  }
+}
\ No newline at end of file
diff --git a/src/components/sidemenu/comtableconfig/columnform/index.jsx b/src/templates/comtableconfig/columnform/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/columnform/index.jsx
rename to src/templates/comtableconfig/columnform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/columnform/index.scss b/src/templates/comtableconfig/columnform/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/columnform/index.scss
rename to src/templates/comtableconfig/columnform/index.scss
diff --git a/src/templates/comtableconfig/dragelement/card.jsx b/src/templates/comtableconfig/dragelement/card.jsx
new file mode 100644
index 0000000..5b4d873
--- /dev/null
+++ b/src/templates/comtableconfig/dragelement/card.jsx
@@ -0,0 +1,89 @@
+import React from 'react'
+import { useDrag, useDrop } from 'react-dnd'
+import { Icon, Button, Select, DatePicker, Input } from 'antd'
+import moment from 'moment'
+import ItemTypes from './itemtypes'
+import './index.scss'
+
+const Card = ({ id, type, card, moveCard, findCard, editCard, copyCard, hasDrop }) => {
+  const originalIndex = findCard(id).index
+  const [{ isDragging }, drag] = useDrag({
+    item: { type: ItemTypes[type], id, originalIndex },
+    collect: monitor => ({
+      isDragging: monitor.isDragging(),
+    }),
+  })
+  const [, drop] = useDrop({
+    accept: ItemTypes[type],
+    canDrop: () => true,
+    drop: (item) => {
+      if (!item.hasOwnProperty('originalIndex')) {
+        hasDrop(card)
+      }
+    },
+    hover({ id: draggedId }) {
+      if (!draggedId) return
+      if (draggedId !== id) {
+        const { index: overIndex } = findCard(id)
+        moveCard(draggedId, overIndex)
+      }
+    },
+  })
+  const opacity = isDragging ? 0 : 1
+
+  const edit = () => {
+    editCard(id)
+  }
+
+  const copy = () => {
+    copyCard(id)
+  }
+
+  return (
+    <div className="page-card" style={type === 'columns' ? { flex: card.Width, opacity: opacity} : { opacity: opacity}}>
+      <div ref={node => drag(drop(node))}>
+        {type === 'search' && <div className="ant-row ant-form-item">
+          <div className="ant-col ant-form-item-label">
+            <label title={card.label}>{card.label}</label>
+          </div>
+          <div className="ant-col ant-form-item-control-wrapper">
+            {card.type === 'text' &&
+              <Input style={{marginTop: '4px'}} defaultValue={card.initval} />
+            }
+            {(card.type === 'select' || card.type === 'link') &&
+              <Select defaultValue={card.initval}></Select>
+            }
+            {card.type === 'date' &&
+              <DatePicker defaultValue={card.initval ? moment(card.initval, 'YYYY-MM-DD') : null} />
+            }
+            {card.type === 'datetime' &&
+              <DatePicker showTime defaultValue={card.initval ? moment(card.initval, 'YYYY-MM-DD HH:mm:ss') : null} />
+            }
+            <div className="input-mask"></div>
+          </div>
+        </div>}
+        {type === 'action' &&
+          <Button
+            className={'mk-btn mk-' + card.class}
+            icon={card.icon}
+            key={card.uuid}
+          >{card.label}{card.position === 'grid' && <Icon type="table" />}</Button>
+        }
+        {type === 'columns' &&
+          <span className="ant-table-header-column">
+            <div className="ant-table-column-sorters" title={card.label} style={{textAlign: card.Align}}>
+              <span className="ant-table-column-title">{card.label}</span>
+              {card.IsSort === 'true' && <span className="ant-table-column-sorter">
+                <Icon type="caret-up" />
+                <Icon type="caret-down" />
+              </span>}
+            </div>
+          </span>
+        }
+      </div>
+      <Icon className="edit" type="edit" onClick={edit} />
+      {type === 'action' && <Icon className="edit copy" type="copy" onClick={copy} />}
+    </div>
+  )
+}
+export default Card
diff --git a/src/components/sidemenu/comtableconfig/dragelement/index.jsx b/src/templates/comtableconfig/dragelement/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/dragelement/index.jsx
rename to src/templates/comtableconfig/dragelement/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/dragelement/index.scss b/src/templates/comtableconfig/dragelement/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/dragelement/index.scss
rename to src/templates/comtableconfig/dragelement/index.scss
diff --git a/src/components/sidemenu/comtableconfig/dragelement/itemtypes.js b/src/templates/comtableconfig/dragelement/itemtypes.js
similarity index 100%
rename from src/components/sidemenu/comtableconfig/dragelement/itemtypes.js
rename to src/templates/comtableconfig/dragelement/itemtypes.js
diff --git a/src/components/sidemenu/comtableconfig/dragelement/source.jsx b/src/templates/comtableconfig/dragelement/source.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/dragelement/source.jsx
rename to src/templates/comtableconfig/dragelement/source.jsx
diff --git a/src/components/sidemenu/comtableconfig/editable/index.jsx b/src/templates/comtableconfig/editable/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/editable/index.jsx
rename to src/templates/comtableconfig/editable/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/editable/index.scss b/src/templates/comtableconfig/editable/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/editable/index.scss
rename to src/templates/comtableconfig/editable/index.scss
diff --git a/src/templates/comtableconfig/editcard/index.jsx b/src/templates/comtableconfig/editcard/index.jsx
new file mode 100644
index 0000000..c7b8b25
--- /dev/null
+++ b/src/templates/comtableconfig/editcard/index.jsx
@@ -0,0 +1,99 @@
+import React, {Component} from 'react'
+import { Row, Col, Icon, Radio } from 'antd'
+import './index.scss'
+
+class EditCardCell extends Component {
+  constructor(props) {
+    super(props)
+
+    this.state = {
+      card: props.card,
+      type: props.type
+    }
+  }
+
+  changeSelect = () => {
+    const { card } = this.state
+    this.setState({
+      card: {...card, selected: !card.selected}
+    })
+  }
+
+  changeType = (e) => {
+    const { card } = this.state
+    this.setState({
+      card: {...card, type: e.target.value}
+    })
+  }
+
+  render() {
+    const { card, type } = this.state
+    let _type = card.type
+    if (type === 'columns') {
+      if (_type !== 'picture') {
+        _type = 'text'
+      }
+    } else if (type === 'search') {
+      if (_type === 'number') {
+        _type = 'text'
+      } else if (_type === 'datetime') {
+        _type = 'date'
+      }
+    }
+    return (
+      <div className={'ant-card ant-card-bordered ' + (card.selected ? 'selected' : '')} >
+        <div className="base" onClick={this.changeSelect}>
+          <Icon type="check" />
+          <p title={card.field}>瀛楁鍚�: <span>{card.field}</span></p>
+          <p title={card.label}>鎻愮ず鏂囧瓧: <span>{card.label}</span></p>
+        </div>
+        {type === 'search' && <Radio.Group onChange={this.changeType} value={_type} disabled={!card.selected}>
+          <Radio value="text">text</Radio>
+          <Radio value="select">select</Radio>
+          <Radio value="date">date</Radio>
+        </Radio.Group>}
+        {type === 'columns' && <Radio.Group onChange={this.changeType} value={_type} disabled={!card.selected}>
+          <Radio value="text">text</Radio>
+          <Radio value="picture">picture</Radio>
+        </Radio.Group>}
+      </div>
+    )
+  }
+}
+
+class EditCard extends Component {
+  constructor(props) {
+    super(props)
+
+    this.state = {
+      dataSource: props.data,
+      type: props.type
+    }
+  }
+
+  getSelectedCard = () => {
+    let box = []
+    this.state.dataSource.forEach((item, index) => {
+      box.push(this.refs['cellCard' + index].state.card)
+    })
+    return box
+  }
+
+  render() {
+    const { dataSource, type } = this.state
+
+    return (
+      <div className="common-modal-edit-card">
+        <Row>
+          {dataSource.map((item, index) => (
+            <Col key={index} span={8}>
+              <EditCardCell ref={'cellCard' + index} type={type} card={item} />
+            </Col>
+          ))}
+        </Row>
+      </div>
+    )
+  }
+}
+
+export default EditCard
\ No newline at end of file
diff --git a/src/templates/comtableconfig/editcard/index.scss b/src/templates/comtableconfig/editcard/index.scss
new file mode 100644
index 0000000..b4cb7ce
--- /dev/null
+++ b/src/templates/comtableconfig/editcard/index.scss
@@ -0,0 +1,43 @@
+.common-modal-edit-card {
+  margin-left: -10px;
+  margin-right: -10px;
+  .ant-col {
+    padding: 10px;
+    .ant-card {
+      padding: 10px;
+      p {
+        margin-bottom: 5px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+      label {
+        margin-right: 15px;
+        span.ant-radio + * {
+          padding-right: 0px;
+          padding-left: 4px;
+        }
+      }
+      .anticon {
+        position: absolute;
+        top: 10px;
+        right: 10px;
+        opacity: 0.4;
+      }
+      .base {
+        cursor: pointer;
+      }
+    }
+    .ant-card.selected {
+      border-color: #1890ff;
+      box-shadow: 0px 0px 4px #1890ff;
+      .anticon {
+        opacity: 1;
+        color: #1890ff;
+      }
+      p {
+        color: #1890ff;
+      }
+    }
+  }
+}
diff --git a/src/templates/comtableconfig/index.jsx b/src/templates/comtableconfig/index.jsx
new file mode 100644
index 0000000..4586930
--- /dev/null
+++ b/src/templates/comtableconfig/index.jsx
@@ -0,0 +1,1448 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { DndProvider } from 'react-dnd'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { Button, Card, Modal, Collapse, notification, Spin, Select, List, Icon, Empty } from 'antd'
+import DragElement from './dragelement'
+import SourceElement from './dragelement/source'
+import Api from '@/api'
+import SearchForm from './searchform'
+import ActionForm from './actionform'
+import ColumnForm from './columnform'
+import SettingForm from './settingform'
+import EditCard from './editcard'
+import MenuForm from './menuform'
+import zhCN from '@/locales/zh-CN/comtable.js'
+import enUS from '@/locales/en-US/comtable.js'
+import Utils from '@/utils/utils.js'
+import Source from './source'
+import './index.scss'
+
+const { Panel } = Collapse
+const { Option } = Select
+const { confirm } = Modal
+const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
+
+class ComTableConfig extends Component {
+  static propTpyes = {
+    type: PropTypes.string,
+    menu: PropTypes.any,
+    handleConfig: PropTypes.func,
+    handleSubConfig: PropTypes.func,
+    supMenuList: PropTypes.array
+  }
+
+  state = {
+    operaType: '', // 鎿嶄綔绫诲瀷锛屾柊寤烘垨缂栬緫
+    dict: CommonDict, // 瀛楀吀
+    config: null, // 椤甸潰閰嶇疆
+    visible: false, // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪锛屾ā鎬佹鏄剧ず鎺у埗
+    tableVisible: false, // 鏁版嵁琛ㄥ瓧娈垫ā鎬佹
+    addType: '', // 娣诲姞绫诲瀷-鎼滅储鏉′欢鎴栨樉绀哄垪
+    tableColumns: [], // 琛ㄦ牸鏄剧ず鍒�
+    fields: null, // 鎼滅储鏉′欢鍙婃樉绀哄垪锛屽彲閫夊瓧娈�
+    menuformlist: null, // 鍩烘湰淇℃伅琛ㄥ崟瀛楁
+    formlist: null, // 鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪琛ㄥ崟瀛楁
+    formtemp: '', // 琛ㄥ崟绫诲瀷锛屾樉绀哄垪銆佹寜閽�佹悳绱㈡潯浠�
+    card: null, // 缂栬緫鍏冪礌
+    searchloading: false, // 鎼滅储鏉′欢鍔犺浇涓�
+    actionloading: false, // 鎸夐挳鍔犺浇涓�
+    columnsloading: false, // 鏄剧ず鍒楀姞杞戒腑
+    menuloading: false, // 鑿滃崟淇濆瓨涓�
+    loading: false, // 鍔犺浇涓紝椤甸潰spin
+    settingVisible: false, // 鍏ㄥ眬閰嶇疆妯℃�佹
+    closeVisible: false, // 鍏抽棴妯℃�佹
+    tables: [], // 鍙敤琛ㄥ悕
+    selectedTables: [], // 宸查�夎〃鍚�
+    originMenu: null // 鍘熷鑿滃崟
+  }
+
+  /**
+   * @description 鏁版嵁棰勫鐞�
+   * 1銆佽缃〉闈㈤厤缃俊鎭紝鏂板缓鎴栨棤閰嶇疆淇℃伅鏃讹紙鍒囨崲妯℃澘鍚庢棤閰嶇疆淇℃伅锛夛紝浣跨敤妯℃澘榛樿閰嶇疆
+   * 2銆佽缃搷浣滅被鍨嬨�佸師濮嬭彍鍗曚俊鎭紙姣忔淇濆瓨鍚庨噸缃級銆佸凡浣跨敤琛ㄥ強鍩烘湰淇℃伅琛ㄥ崟
+   */
+  UNSAFE_componentWillMount () {
+    const { menu } = this.props
+
+    let _LongParam = menu.LongParam
+    let _config = ''
+    if (this.props.type === 'add' || !_LongParam) {
+      _config = JSON.parse(JSON.stringify((Source.baseConfig)))
+    } else {
+      let _setting = Source.baseConfig.setting
+      if (_LongParam.setting) {
+        _setting = {..._setting, ..._LongParam.setting}
+      }
+      _LongParam.setting = _setting
+      _config = _LongParam
+    }
+
+    this.setState({
+      config: _config,
+      operaType: this.props.type,
+      originMenu: JSON.parse(JSON.stringify({...menu})),
+      selectedTables: _config.tables || [],
+      menuformlist: [
+        {
+          type: 'select',
+          key: 'parentId',
+          label: this.state.dict['header.menu.supMenu'],
+          initVal: menu.ParentID,
+          required: true,
+          readonly: false,
+          options: this.props.supMenuList
+        },
+        {
+          type: 'text',
+          key: 'menuName',
+          label: this.state.dict['header.menu.menuName'],
+          initVal: menu.MenuName,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'menuNo',
+          label: this.state.dict['header.menu.menuNo'],
+          initVal: menu.MenuNo,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'opentype',
+          label: this.state.dict['header.menu.openType'],
+          initVal: menu.PageParam.OpenType,
+          required: true,
+          options: [{
+            MenuID: 'newtab',
+            text: this.state.dict['header.form.tab']
+          }, {
+            MenuID: 'newpage',
+            text: this.state.dict['header.form.newpage']
+          }]
+        }
+      ]
+    })
+  }
+
+  /**
+   * @description 鍔犺浇瀹屾垚鍚�
+   * 1銆佽幏鍙栫郴缁熷彲浣跨敤琛�
+   * 2銆佹牴鎹厤缃俊鎭腑宸蹭娇鐢ㄨ〃鑾峰彇鐩稿叧瀛楁淇℃伅
+   */
+  componentDidMount () {
+    let _text = "select TbName ,Remark from sDataDictionary where IsKey!='' and Deleted =0"
+    _text = Utils.formatOptions(_text)
+
+    Api.getSystemConfig({func: 'sPC_Get_SelectedList', LText: _text, obj_name: 'data', arr_field: 'TbName,Remark'}).then(res => {
+      if (res.status) {
+        this.setState({
+          tables: res.data
+        })
+      } else {
+        notification.warning({
+          top: 92,
+          message: res.message,
+          duration: 10
+        })
+      }
+    })
+
+    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,
+                decimal: _decimal
+              }
+            })
+          }
+          _columns.push(tabmsg)
+        } else {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+        }
+      })
+
+      this.setState({
+        tableColumns: _columns
+      })
+    })
+  }
+
+  handleList = (listObj) => {
+    let config = this.state.config
+    if (this.state.operaType === 'add') {
+      let key = Object.keys(listObj)[0]
+      let newlength = listObj[key].length
+      if (newlength > config[key].length) {
+        listObj[key] = listObj[key].filter(item => !item.origin)
+      }
+      if (newlength > listObj[key].length) {
+        this.setState({
+          [key + 'loading']: true,
+          config: {...config, ...listObj}
+        }, () => {
+          // 鍒锋柊瀵瑰簲鐨勯厤缃俊鎭�
+          this.setState({
+            [key + 'loading']: false
+          })
+        })
+      } else {
+        this.setState({config: {...config, ...listObj}})
+      }
+    } else {
+      this.setState({config: {...config, ...listObj}})
+    }
+  }
+
+  handleSearch = (card) => {
+    this.setState({
+      visible: true,
+      formtemp: 'search',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'field',
+          label: this.state.dict['header.form.field'],
+          initVal: card.field,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'type',
+          label: this.state.dict['header.form.type'],
+          initVal: card.type,
+          required: true,
+          options: [{
+            MenuID: 'text',
+            text: this.state.dict['header.form.text']
+          }, {
+            MenuID: 'select',
+            text: this.state.dict['header.form.select']
+          }, {
+            MenuID: 'link',
+            text: this.state.dict['header.form.link']
+          }, {
+            MenuID: 'date',
+            text: this.state.dict['header.form.dateday']
+          }, {
+            MenuID: 'datetime',
+            text: this.state.dict['header.form.datetime']
+          }]
+        },
+        {
+          type: 'text',
+          key: 'initval',
+          label: this.state.dict['header.form.initval'],
+          initVal: card.initval,
+          required: false
+        },
+        {
+          type: 'radio',
+          key: 'resourceType',
+          label: this.state.dict['header.form.resourceType'],
+          initVal: card.resourceType || '0',
+          required: true,
+          options: [{
+            MenuID: '0',
+            text: this.state.dict['header.form.custom']
+          }, {
+            MenuID: '1',
+            text: this.state.dict['header.form.datasource']
+          }]
+        },
+        {
+          type: 'radio',
+          key: 'setAll',
+          label: this.state.dict['header.form.setAll'],
+          initVal: card.setAll || 'false',
+          options: [{
+            MenuID: 'true',
+            text: this.state.dict['header.form.true']
+          }, {
+            MenuID: 'false',
+            text: this.state.dict['header.form.false']
+          }]
+        },
+        {
+          type: 'textarea',
+          key: 'dataSource',
+          label: this.state.dict['header.form.datasource'],
+          initVal: card.dataSource || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'options',
+          key: 'options',
+          label: '',
+          initVal: card.options || [],
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'linkField',
+          label: this.state.dict['header.form.linkField'],
+          initVal: card.linkField || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'valueField',
+          label: this.state.dict['header.form.valueField'],
+          initVal: card.valueField || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'valueText',
+          label: this.state.dict['header.form.valueText'],
+          initVal: card.valueText || '',
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'orderBy',
+          label: this.state.dict['header.form.orderBy'],
+          initVal: card.orderBy || '',
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'orderType',
+          label: this.state.dict['header.form.orderType'],
+          initVal: card.orderType || 'asc',
+          options: [{
+            MenuID: 'asc',
+            text: this.state.dict['header.form.asc']
+          }, {
+            MenuID: 'desc',
+            text: this.state.dict['header.form.desc']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'match',
+          label: this.state.dict['header.form.match'],
+          initVal: card.match || 'like',
+          required: true,
+          options: [{
+            MenuID: 'like',
+            text: 'like'
+          }, {
+            MenuID: 'equal',
+            text: 'equal'
+          }, {
+            MenuID: 'greater',
+            text: '>'
+          }, {
+            MenuID: 'less',
+            text: '<'
+          }, {
+            MenuID: 'greaterequal',
+            text: '>='
+          }]
+        },
+        {
+          type: 'select',
+          key: 'display',
+          label: this.state.dict['header.form.display'],
+          initVal: card.display || 'dropdown',
+          required: true,
+          options: [{
+            MenuID: 'dropdown',
+            text: this.state.dict['header.form.dropdown']
+          }, {
+            MenuID: 'button',
+            text: this.state.dict['header.form.button']
+          }]
+        }
+      ]
+    })
+  }
+
+  handleAction = (card) => {
+    this.setState({
+      visible: true,
+      formtemp: 'action',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'OpenType',
+          label: this.state.dict['header.form.openType'],
+          initVal: card.OpenType,
+          required: true,
+          options: [{
+            MenuID: 'pop',
+            text: this.state.dict['header.form.pop']
+          }, {
+            MenuID: 'prompt',
+            text: this.state.dict['header.form.prompt']
+          }, {
+            MenuID: 'exec',
+            text: this.state.dict['header.form.exec']
+          }, {
+            MenuID: 'tab',
+            text: this.state.dict['header.form.tab']
+          }, {
+            MenuID: 'blank',
+            text: this.state.dict['header.form.blank']
+          }, {
+            MenuID: 'newpage',
+            text: this.state.dict['header.form.newpage']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'position',
+          label: this.state.dict['header.form.position'],
+          initVal: card.position || 'toolbar',
+          required: true,
+          options: [{
+            MenuID: 'toolbar',
+            text: this.state.dict['header.form.toolbar']
+          }, {
+            MenuID: 'grid',
+            text: this.state.dict['header.form.grid']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'pageTemplate',
+          label: this.state.dict['header.form.pageTemplate'],
+          initVal: card.pageTemplate,
+          required: true,
+          options: []
+        },
+        {
+          type: 'text',
+          key: 'innerFunc',
+          label: this.state.dict['header.form.innerFunc'],
+          initVal: card.innerFunc,
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'Ot',
+          label: this.state.dict['header.form.isRequired'],
+          initVal: card.Ot,
+          required: true,
+          options: [{
+            MenuID: 'notRequired',
+            text: this.state.dict['header.form.notRequired']
+          }, {
+            MenuID: 'requiredSgl',
+            text: this.state.dict['header.form.requiredSgl']
+          }, {
+            MenuID: 'required',
+            text: this.state.dict['header.form.required']
+          }, {
+            MenuID: 'requiredOnce',
+            text: this.state.dict['header.form.requiredOnce']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'icon',
+          label: this.state.dict['header.form.icon'],
+          initVal: card.icon,
+          required: false,
+          options: []
+        },
+        {
+          type: 'select',
+          key: 'class',
+          label: this.state.dict['header.form.class'],
+          initVal: card.class,
+          required: false,
+          options: []
+        },
+        {
+          type: 'radio',
+          key: 'intertype',
+          label: this.state.dict['header.form.intertype'],
+          initVal: card.intertype,
+          required: true,
+          options: [{
+            MenuID: 'inner',
+            text: this.state.dict['header.form.interface.inner']
+          }, {
+            MenuID: 'outer',
+            text: this.state.dict['header.form.interface.outer']
+          }]
+        },
+        {
+          type: 'text',
+          key: 'interface',
+          label: this.state.dict['header.form.interface'],
+          initVal: card.interface,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'outerFunc',
+          label: this.state.dict['header.form.outerFunc'],
+          initVal: card.outerFunc,
+          required: false,
+          readonly: false
+        },
+        {
+          type: 'text',
+          key: 'callbackFunc',
+          label: this.state.dict['header.form.callbackFunc'],
+          initVal: card.callbackFunc,
+          required: false,
+          readonly: false
+        }
+      ]
+    })
+  }
+
+  handleColumn = (card) => {
+    this.setState({
+      visible: true,
+      formtemp: 'columns',
+      card: card,
+      formlist: [
+        {
+          type: 'text',
+          key: 'label',
+          label: this.state.dict['header.form.name'],
+          initVal: card.label,
+          required: true
+        },
+        {
+          type: 'text',
+          key: 'field',
+          label: this.state.dict['header.form.field'],
+          initVal: card.field,
+          required: true,
+          readonly: false
+        },
+        {
+          type: 'select',
+          key: 'type',
+          label: this.state.dict['header.form.type'],
+          initVal: card.type,
+          required: true,
+          options: [{
+            MenuID: 'text',
+            text: this.state.dict['header.form.text']
+          }, {
+            MenuID: 'picture',
+            text: this.state.dict['header.form.picture']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'Align',
+          label: this.state.dict['header.form.align'],
+          initVal: card.Align,
+          required: true,
+          options: [{
+            MenuID: 'left',
+            text: this.state.dict['header.form.alignLeft']
+          }, {
+            MenuID: 'right',
+            text: this.state.dict['header.form.alignRight']
+          }, {
+            MenuID: 'center',
+            text: this.state.dict['header.form.alignCenter']
+          }]
+        },
+        {
+          type: 'radio',
+          key: 'Hide',
+          label: this.state.dict['header.form.Hide'],
+          initVal: card.Hide,
+          required: true,
+          options: [{
+            MenuID: 'true',
+            text: this.state.dict['header.form.true']
+          }, {
+            MenuID: 'false',
+            text: this.state.dict['header.form.false']
+          }]
+        },
+        {
+          type: 'select',
+          key: 'IsSort',
+          label: this.state.dict['header.form.IsSort'],
+          initVal: card.IsSort,
+          required: true,
+          options: [{
+            MenuID: 'true',
+            text: this.state.dict['header.form.true']
+          }, {
+            MenuID: 'false',
+            text: this.state.dict['header.form.false']
+          }]
+        },
+        {
+          type: 'number',
+          key: 'Width',
+          decimal: 0,
+          label: this.state.dict['header.form.columnWidth'],
+          initVal: card.Width,
+          required: true
+        }
+      ]
+    })
+  }
+
+  handleSubmit = () => {
+    this.formRef.handleConfirm().then(res => {
+      let _config = this.state.config
+
+      if (this.state.operaType === 'add') {
+        _config[res.type] = _config[res.type].map(item => {
+          if (item.uuid === res.values.uuid) {
+            return res.values
+          } else {
+            return item
+          }
+        })
+        _config[res.type] = _config[res.type].filter(item => !item.origin)
+      } else {
+        _config[res.type] = _config[res.type].map(item => {
+          if (item.uuid === res.values.uuid) {
+            return res.values
+          } else {
+            return item
+          }
+        })
+      }
+
+      this.setState({
+        config: _config,
+        [res.type + 'loading']: true,
+        visible: false
+      }, () => {
+        this.setState({
+          [res.type + 'loading']: false
+        })
+      })
+    })
+  }
+
+  deleteElement = () => {
+    let _config = this.state.config
+    _config[this.state.formtemp] = _config[this.state.formtemp].filter(item => {
+      if (item.uuid === this.state.card.uuid) {
+        return false
+      } else {
+        return true
+      }
+    })
+    this.setState({
+      config: _config,
+      [this.state.formtemp + 'loading']: true,
+      visible: false
+    }, () => {
+      this.setState({
+        [this.state.formtemp + 'loading']: false
+      })
+    })
+  }
+
+  changeTemplate = () => {
+    this.props.handleConfig('template')
+  }
+
+  submitConfig = () => {
+    const { menu } = this.props
+    const { config, originMenu } = this.state
+    this.menuformRef.handleConfirm().then(res => {
+      if (config.search[0] && config.search[0].origin) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃悳绱㈡潯浠�',
+          duration: 10
+        })
+        return
+      }
+      if (config.action[0] && config.action[0].origin) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃寜閽�',
+          duration: 10
+        })
+        return
+      }
+      if (config.columns[0] && config.columns[0].origin) {
+        notification.warning({
+          top: 92,
+          message: '璇疯缃樉绀哄垪',
+          duration: 10
+        })
+        return
+      }
+
+      let _LongParam = ''
+      let _config = {...config, tables: this.state.selectedTables}
+      let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+
+      try {
+        _LongParam = window.btoa(window.encodeURIComponent(JSON.stringify(_config)))
+      } catch (e) {
+        notification.warning({
+          top: 92,
+          message: '缂栬瘧閿欒',
+          duration: 10
+        })
+        return
+      }
+
+      if (this.state.operaType === 'add') {
+        let param = {
+          func: 'sPC_TrdMenu_Add',
+          ParentID: res.parentId,
+          MenuID: menu.MenuID,
+          MenuNo: res.menuNo,
+          Template: menu.PageParam.Template || '',
+          MenuName: res.menuName,
+          PageParam: JSON.stringify(_pageParam),
+          LongParam: _LongParam
+        }
+        this.setState({
+          menuloading: true
+        })
+
+        Api.getSystemConfig(param).then(response => {
+          if (response.status) {
+            this.setState({
+              menuloading: false,
+              operaType: 'edit',
+              originMenu: {
+                ...originMenu,
+                LongParam: _config,
+                PageParam: _pageParam,
+                MenuName: res.menuName,
+                MenuNo: res.menuNo,
+                ParentID: res.parentId
+              }
+            })
+            notification.success({
+              top: 92,
+              message: '淇濆瓨鎴愬姛',
+              duration: 10
+            })
+          } else {
+            this.setState({
+              menuloading: false
+            })
+            notification.warning({
+              top: 92,
+              message: response.message,
+              duration: 10
+            })
+          }
+        })
+      } else {
+        let param = {
+          func: 'sPC_TrdMenu_Upt',
+          ParentID: res.parentId,
+          MenuID: menu.MenuID,
+          MenuNo: res.menuNo,
+          Template: menu.PageParam.Template || '',
+          MenuName: res.menuName,
+          PageParam: JSON.stringify(_pageParam),
+          LongParam: _LongParam
+        }
+        this.setState({
+          menuloading: true
+        })
+
+        Api.getSystemConfig(param).then(response => {
+          if (response.status) {
+            notification.success({
+              top: 92,
+              message: '淇濆瓨鎴愬姛',
+              duration: 10
+            })
+            if (this.state.closeVisible) {
+              this.props.handleConfig('')
+            } else {
+              this.setState({
+                menuloading: false,
+                originMenu: {
+                  ...originMenu,
+                  LongParam: _config,
+                  PageParam: _pageParam,
+                  MenuName: res.menuName,
+                  MenuNo: res.menuNo,
+                  ParentID: res.parentId
+                }
+              })
+            }
+          } else {
+            this.setState({
+              menuloading: false
+            })
+            notification.warning({
+              top: 92,
+              message: response.message,
+              duration: 10
+            })
+          }
+        })
+      }
+    }, () => {
+      notification.warning({
+        top: 92,
+        message: this.state.dict['header.menu.basemsg'],
+        duration: 10
+      })
+    })
+  }
+
+  cancelConfig = () => {
+    const { menu } = this.props
+    const { config, originMenu } = this.state
+    let _this = this
+
+    if (this.state.operaType === 'add') {
+      confirm({
+        content: '鑿滃崟灏氭湭鎻愪氦锛岀‘瀹氭斁寮冧繚瀛樺悧锛�',
+        okText: this.state.dict['header.confirm'],
+        cancelText: this.state.dict['header.cancel'],
+        onOk() {
+          _this.props.handleConfig('')
+        },
+        onCancel() {}
+      })
+    } else {
+      this.menuformRef.handleConfirm().then(res => {
+        let _config = {...config, tables: this.state.selectedTables}
+        let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+        let _originMenu = {
+          ...originMenu,
+          LongParam: _config,
+          PageParam: _pageParam,
+          MenuName: res.menuName,
+          MenuNo: res.menuNo,
+          ParentID: res.parentId
+        }
+
+        if (!is(fromJS(originMenu), fromJS(_originMenu))) {
+          this.setState({
+            closeVisible: true
+          })
+        } else {
+          this.props.handleConfig('')
+        }
+      }, () => {
+        this.setState({
+          closeVisible: true
+        })
+      })
+    }
+  }
+
+  queryField = (type) => {
+    const {selectedTables, tableColumns, config} = this.state
+    if (selectedTables.length === 0) {
+      notification.warning({
+        top: 92,
+        message: '璇烽�夋嫨琛ㄥ悕锛�',
+        duration: 10
+      })
+      return
+    }
+
+    let columns = new Map()
+    tableColumns.forEach(table => {
+      table.columns.forEach(column => {
+        columns.set(column.field, column)
+      })
+    })
+
+    if (type === 'search') {
+      config.search.forEach(item => {
+        if (columns.has(item.field)) {
+          columns.set(item.field, {...item, selected: true, type: item.type})
+        }
+      })
+    } else if (type === 'columns') {
+      config.columns.forEach(item => {
+        if (columns.has(item.field)) {
+          columns.set(item.field, {...item, selected: true, type: item.type})
+        }
+      })
+    }
+
+    this.setState({
+      addType: type,
+      tableVisible: true,
+      fields: [...columns.values()]
+    })
+  }
+
+  addFieldSubmit = () => {
+    if (!this.state.fields || this.state.fields.length === 0) {
+      this.setState({
+        tableVisible: false,
+        addType: ''
+      })
+    }
+
+    const {addType, config} = this.state
+
+    let cards = this.refs.searchcard.getSelectedCard()
+    let columns = new Map()
+    cards.forEach(card => {
+      columns.set(card.field, card)
+    })
+
+    let items = []
+    if (addType === 'search') {
+      config.search.forEach(item => {
+        if (columns.has(item.field)) {
+          let cell = columns.get(item.field)
+
+          if (cell.selected) {
+            items.push(item)
+          }
+          columns.delete(item.field)
+        } else if (!item.origin) {
+          items.push(item)
+        }
+      })
+
+      let _columns = [...columns.values()]
+      let indexes = items.map(card => {return card.id})
+      let id = Math.max(...indexes, 0)
+
+      _columns.forEach(item => {
+        if (item.selected) {
+          let newcard = {
+            id: id,
+            uuid: Utils.getuuid(),
+            label: item.label,
+            field: item.field,
+            initval: '',
+            type: item.type,
+            resourceType: '0',
+            setAll: 'false',
+            options: [],
+            dataSource: '',
+            linkField: '',
+            valueField: '',
+            valueText: '',
+            orderBy: '',
+            orderType: 'asc',
+            display: 'dropdown'
+          }
+
+          items.push(newcard)
+          id++
+        }
+      })
+    } else {
+      config.columns.forEach(item => {
+        if (columns.has(item.field)) {
+          let cell = columns.get(item.field)
+
+          if (cell.selected) {
+            items.push(item)
+          }
+          columns.delete(item.field)
+        } else if (!item.origin) {
+          items.push(item)
+        }
+      })
+
+      let _columns = [...columns.values()]
+      let indexes = items.map(card => {return card.id})
+      let id = Math.max(...indexes, 0)
+
+      _columns.forEach(item => {
+        if (item.selected) {
+          let newcard = {
+            id: id,
+            uuid: Utils.getuuid(),
+            Align: 'left',
+            label: item.label,
+            field: item.field,
+            Hide: 'false',
+            IsSort: 'true',
+            type: 'text',
+            Width: 120
+          }
+
+          items.push(newcard)
+          id++
+        }
+      })
+    }
+
+    this.setState({
+      tableVisible: false,
+      [addType + 'loading']: true,
+      addType: '',
+      config: {...config, [addType]: items}
+    }, () => {
+      this.setState({
+        [addType + 'loading']: false
+      })
+    })
+  }
+
+  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)
+                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,
+                decimal: _decimal
+              }
+            })
+          }
+          this.setState({
+            tableColumns: [...tableColumns, tabmsg]
+          })
+        } else {
+          notification.warning({
+            top: 92,
+            message: res.message,
+            duration: 10
+          })
+        }
+      })
+    }
+  }
+
+  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 = () => {
+    this.setState({
+      settingVisible: true
+    })
+  }
+
+  settingSave = () => {
+    const {config} = this.state
+    this.settingRef.handleConfirm().then(res => {
+      this.setState({
+        config: {...config, setting: res},
+        settingVisible: false
+      })
+    })
+  }
+
+  setSubConfig = (btn) => {
+    const { menu } = this.props
+    const { config, originMenu } = this.state
+
+    if (this.state.operaType === 'add') {
+      notification.warning({
+        top: 92,
+        message: '鑿滃崟灏氭湭淇濆瓨锛岃淇濆瓨鑿滃崟閰嶇疆锛�',
+        duration: 10
+      })
+    } else {
+      this.menuformRef.handleConfirm().then(res => {
+        let _config = {...config, tables: this.state.selectedTables}
+        let _pageParam = {...menu.PageParam, OpenType: res.opentype}
+        let _originMenu = {
+          ...originMenu,
+          LongParam: _config,
+          PageParam: _pageParam,
+          MenuName: res.menuName,
+          MenuNo: res.menuNo,
+          ParentID: res.parentId
+        }
+
+        if (!is(fromJS(originMenu), fromJS(_originMenu))) {
+          notification.warning({
+            top: 92,
+            message: '鑿滃崟閰嶇疆宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
+            duration: 10
+          })
+        } else {
+          this.setState({
+            loading: true
+          })
+          Api.getSystemConfig({
+            func: 'sPC_Get_FrozenMenu',
+            ParentID: btn.uuid,
+            TYPE: 30
+          }).then(res => {
+            if (res.status) {
+              let btnconfig = ''
+              this.setState({
+                loading: false
+              })
+              this.props.handleSubConfig(btn, originMenu, btnconfig)
+            } else {
+              this.setState({
+                loading: false
+              })
+              notification.warning({
+                top: 92,
+                message: res.message,
+                duration: 10
+              })
+            }
+          })
+        }
+      }, () => {
+        notification.warning({
+          top: 92,
+          message: '鑿滃崟鍩烘湰淇℃伅宸蹭慨鏀癸紝璇蜂繚瀛橈紒',
+          duration: 10
+        })
+      })
+    }
+  }
+
+  render () {
+    const configAction = this.state.config.action.filter(_action => !_action.origin && (_action.OpenType === 'pop'))
+    return (
+      <div className="common-table-board">
+        <DndProvider backend={HTML5Backend}>
+          {/* 宸ュ叿鏍� */}
+          <div className="tools">
+            <Collapse accordion defaultActiveKey="0" bordered={false}>
+              <Panel header="鍩烘湰淇℃伅" key="0" id="common-basedata">
+                <MenuForm
+                  dict={this.state.dict}
+                  formlist={this.state.menuformlist}
+                  wrappedComponentRef={(inst) => this.menuformRef = inst}
+                />
+                <div className="ant-col ant-form-item-label">
+                  <label title="娣诲姞琛ㄥ悕">娣诲姞琛ㄥ悕</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} 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 + ')'}
+                    <Icon type="close" onClick={() => this.deleteTable(item)}/>
+                    <div className="bottom-mask"></div>
+                  </List.Item>}
+                />}
+              </Panel>
+              <Panel header="鎼滅储" key="1">
+                <div className="search-element">
+                  {Source.searchItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                <Button type="primary" block onClick={() => this.queryField('search')}>娣诲姞鎼滅储鏉′欢</Button>
+              </Panel>
+              <Panel header="鎸夐挳" key="2">
+                <div className="search-element">
+                  {Source.actionItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                {configAction.length > 0 ?
+                  <div>
+                    <p style={{marginTop: '20px', marginBottom: '10px', color: '#1890ff'}}>鍙厤缃寜閽細</p>
+                    {configAction.map((item, index) => {
+                      return (
+                        <div key={index}>
+                          <Button
+                            icon={item.icon}
+                            style={{marginBottom: '10px'}}
+                            className={'mk-btn mk-' + item.class}
+                            onClick={() => this.setSubConfig(item)}
+                          >{item.label}</Button>
+                        </div>
+                      )
+                    })}
+                  </div> : null
+                }
+              </Panel>
+              <Panel header="鏄剧ず鍒�" key="3">
+                <div className="search-element">
+                  {Source.columnItems.map((item, index) => {
+                    return (<SourceElement key={index} content={item}/>)
+                  })}
+                </div>
+                <Button type="primary" block onClick={() => this.queryField('columns')}>娣诲姞鏄剧ず鍒�</Button>
+              </Panel>
+            </Collapse>
+          </div>
+          <div className="setting">
+            <Card title="椤甸潰閰嶇疆" bordered={false} extra={
+              <div>
+                <Button type="primary" onClick={this.changeTemplate}>{this.state.dict['header.menu.template.change']}</Button>
+                <Button type="primary" onClick={this.submitConfig} loading={this.state.menuloading}>{this.state.dict['header.save']}</Button>
+                <Button onClick={this.cancelConfig}>{this.state.dict['header.return']}</Button>
+              </div>
+            } style={{ width: '100%' }}>
+              <Icon type="setting" onClick={this.changeSetting} />
+              <div className="search-list">
+                {this.state.config.search && !this.state.searchloading &&
+                <DragElement
+                  list={this.state.config.search}
+                  type="search"
+                  placeholder={this.state.dict['header.form.search.placeholder']}
+                  handleList={this.handleList}
+                  handleMenu={this.handleSearch}
+                />}
+              </div>
+              <div className="action-list">
+                {this.state.config.action && !this.state.actionloading &&
+                <DragElement
+                  list={this.state.config.action}
+                  type="action"
+                  placeholder={this.state.dict['header.form.action.placeholder']}
+                  handleList={this.handleList}
+                  handleMenu={this.handleAction}
+                />}
+              </div>
+              <div className="column-list">
+                {this.state.config.columns && !this.state.columnsloading &&
+                <DragElement
+                  list={this.state.config.columns}
+                  type="columns"
+                  placeholder={this.state.dict['header.form.column.placeholder']}
+                  handleList={this.handleList}
+                  handleMenu={this.handleColumn}
+                />}
+              </div>
+            </Card>
+          </div>
+        </DndProvider>
+        {/* 缂栬緫鎼滅储鏉′欢銆佹寜閽�佹樉绀哄垪 */}
+        <Modal
+          title={this.state.dict['header.edit']}
+          visible={this.state.visible}
+          width={700}
+          onCancel={() => { this.setState({ visible: false }) }}
+          footer={[
+            <Button key="delete" type="danger" onClick={this.deleteElement}>{this.state.dict['header.delete']}</Button>,
+            <Button key="cancel" onClick={() => { this.setState({ visible: false }) }}>{this.state.dict['header.cancel']}</Button>,
+            <Button key="confirm" type="primary" onClick={this.handleSubmit}>{this.state.dict['header.confirm']}</Button>
+          ]}
+          destroyOnClose
+        >
+          {this.state.formtemp === 'search' && <SearchForm
+            dict={this.state.dict}
+            formlist={this.state.formlist}
+            card={this.state.card}
+            wrappedComponentRef={(inst) => this.formRef = inst}
+          />}
+          {this.state.formtemp === 'action' && <ActionForm
+            dict={this.state.dict}
+            card={this.state.card}
+            formlist={this.state.formlist}
+            wrappedComponentRef={(inst) => this.formRef = inst}
+          />}
+          {this.state.formtemp === 'columns' && <ColumnForm
+            dict={this.state.dict}
+            card={this.state.card}
+            formlist={this.state.formlist}
+            wrappedComponentRef={(inst) => this.formRef = inst}
+          />}
+        </Modal>
+        {/* 鏍规嵁瀛楁鍚嶆坊鍔犳樉绀哄垪鍙婃悳绱㈡潯浠� */}
+        <Modal
+          wrapClassName="common-table-fields-modal"
+          title={this.state.dict['header.edit']}
+          visible={this.state.tableVisible}
+          width={'65vw'}
+          style={{minWidth: '900px', maxWidth: '1200px'}}
+          onOk={this.addFieldSubmit}
+          onCancel={() => { // 鍙栨秷娣诲姞
+            this.setState({
+              tableVisible: false,
+              addType: ''
+            })
+          }}
+          destroyOnClose
+        >
+          {this.state.addType === 'search' && this.state.fields.length > 0 &&
+            <EditCard data={this.state.fields} ref="searchcard" type="search" />
+          }
+          {this.state.addType === 'columns' && this.state.fields.length > 0 &&
+            <EditCard data={this.state.fields} ref="searchcard" type="columns" />
+          }
+          {(!this.state.fields || this.state.fields.length === 0) &&
+            <Empty />
+          }
+        </Modal>
+        {/* 璁剧疆鍏ㄥ眬閰嶇疆鍙婂垪琛ㄦ暟鎹簮 */}
+        <Modal
+          title={this.state.dict['header.edit']}
+          visible={this.state.settingVisible}
+          width={700}
+          onOk={this.settingSave}
+          onCancel={() => { // 鍙栨秷淇敼
+            this.setState({
+              settingVisible: false
+            })
+          }}
+          destroyOnClose
+        >
+          <SettingForm
+            data={this.state.config.setting}
+            dict={this.state.dict}
+            wrappedComponentRef={(inst) => this.settingRef = inst}
+          />
+        </Modal>
+        <Modal
+          bodyStyle={{textAlign: 'center', color: '#000000', fontSize: '16px'}}
+          closable={false}
+          visible={this.state.closeVisible}
+          onCancel={() => { this.setState({closeVisible: false}) }}
+          footer={[
+            <Button key="save" className="mk-btn mk-green" onClick={this.submitConfig}>{this.state.dict['header.save']}</Button>,
+            <Button key="confirm" className="mk-btn mk-yellow" onClick={() => {this.props.handleConfig('')}}>{this.state.dict['header.notsave']}</Button>,
+            <Button key="cancel" onClick={() => { this.setState({closeVisible: false}) }}>{this.state.dict['header.cancel']}</Button>
+          ]}
+          destroyOnClose
+        >
+          鑿滃崟閰嶇疆宸蹭慨鏀癸紝鏄惁淇濆瓨閰嶇疆淇℃伅锛�
+        </Modal>
+        {this.state.loading && <Spin size="large" />}
+      </div>
+    )
+  }
+}
+
+export default ComTableConfig
\ No newline at end of file
diff --git a/src/templates/comtableconfig/index.scss b/src/templates/comtableconfig/index.scss
new file mode 100644
index 0000000..2041d7d
--- /dev/null
+++ b/src/templates/comtableconfig/index.scss
@@ -0,0 +1,368 @@
+.common-table-board {
+  position: fixed;
+  z-index: 1070;
+  padding-top: 48px;
+  top: 0px;
+  left: 0px;
+  right: 0px;
+  bottom: 0px;
+  background: rgba(0, 0, 0, 0.35);
+  display: flex;
+  .tools {
+    flex: 1;
+    background: #ffffff;
+    border-right: 1px solid #d9d9d9;
+    height: 100%;
+    overflow-y: auto;
+    padding-bottom: 30px;
+    .ant-collapse-item {
+      position: relative;
+      border: 0;
+    }
+    .ant-input-search {
+      margin-top: 10px;
+    }
+    .ant-collapse-item.ant-collapse-item-active {
+      border-bottom: 1px solid #d9d9d9;
+    }
+    .ant-collapse-header {
+      padding: 11px 16px 10px 40px;
+      border-bottom: 1px solid #d9d9d9;
+    }
+    .ant-collapse-content-box {
+      .ant-form-item {
+        margin-bottom: 10px;
+        .ant-form-item-label {
+          text-align: left;
+          height: 25px;
+          line-height: 25px;
+        }
+      }
+    }
+    .search-element {
+      padding-top: 10px;
+      li {
+        padding: 0px 16px 10px;
+        div {
+          cursor: move;
+        }
+      }
+    }
+    .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;
+        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;
+        }
+      }
+    }
+  }
+  
+  .tools::-webkit-scrollbar {
+    width: 7px;
+  }
+  .tools::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
+    background: rgba(0, 0, 0, 0);
+  }
+  .tools::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0);
+    background: rgba(0, 0, 0, 0);
+  }
+  .tools:hover::-webkit-scrollbar-thumb {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .tools:hover::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border: 1px solid rgba(0, 0, 0, 0.07);
+  }
+  .setting {
+    position: relative;
+    width: calc(100vw - 235px);
+    height: 100%;
+    overflow-y: hidden;
+    background: #ffffff;
+    .ant-card-head {
+      min-height: 44px;
+    }
+    .ant-card-head-title {
+      padding: 5px 0;
+      color: #1890ff;
+    }
+    .ant-card-extra {
+      padding: 5px 0;
+      button {
+        margin-left: 20px;
+      }
+    }
+    .ant-card-body {
+      position: relative;
+      padding: 0;
+
+      .search-list {
+        padding: 1px 24px 20px;
+        min-height: 87px;
+        border-bottom: 1px solid #d9d9d9;
+        > .ant-row {
+          min-height: 65px;
+        }
+        .ant-row .ant-col-6 {
+          padding: 0 12px!important;
+        }
+        .ant-row.ant-form-item .ant-col {
+          padding: 0;
+        }
+        .page-card {
+          position: relative;
+          background: #ffffff;
+          border-radius: 2px;
+          padding-top: 15px;
+          .ant-form-item {
+            cursor: move;
+            display: flex;
+            margin-bottom: 0px;
+            .ant-form-item-label {
+              width: 100px;
+              height: 40px;
+              label {
+                width: 100%;
+                cursor: move;
+                overflow: hidden;
+                display: inline-block;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
+            }
+            .ant-form-item-control-wrapper {
+              flex: 1 1;
+              .ant-select {
+                width: 100%;
+                margin-top: 4px;
+              }
+              .ant-calendar-picker {
+                margin-top: 4px;
+              }
+              .input-mask {
+                position: absolute;
+                top: 0;
+                left: 0;
+                right: 0;
+                bottom: 0;
+                opacity: 0;
+              }
+            }
+          }
+          .edit {
+            position: absolute;
+            left: 0;
+            top: 5px;
+            cursor: pointer;
+            display: none;
+          }
+        }
+        .page-card:hover {
+          .edit {
+            display: inline-block;
+          }
+        }
+        .ant-calendar-picker {
+          min-width: 100px!important;
+        }
+      }
+      .action-list {
+        padding: 0px 20px 15px;
+        min-height: 82px;
+        > .ant-row {
+          min-height: 67px;
+        }
+        .page-card {
+          display: inline-block;
+          margin: 0px 0px 0px 0px;
+          padding: 15px 10px 0 0;
+          position: relative;
+          div {
+            cursor: move;
+          }
+          .edit {
+            position: absolute;
+            left: 0;
+            top: 0px;
+            cursor: pointer;
+            display: none;
+          }
+          .edit.copy {
+            left: 20px;
+          }
+          button {
+            cursor: move;
+            .anticon-table {
+              font-size: 10px;
+              position: absolute;
+              right: 1px;
+              bottom: 0px;
+            }
+          }
+        }
+        .page-card:hover {
+          .edit {
+            display: inline-block;
+          }
+        }
+      }
+      .element-add {
+        font-size: 20px;
+        padding: 10px 20px;
+        cursor: pointer;
+      }
+      .column-list {
+        padding: 0px 20px;
+        > .ant-row {
+          background: #fafafa;
+          border-radius: 4px;
+          min-height: 47px;
+          border: 1px solid #e8e8e8;
+          .column-box {
+            display: flex;
+          }
+          .column-box:not(:first-child) {
+            border-top: 1px solid #e8e8e8;
+          }
+          .page-card {
+            position: relative;
+            padding: 0px;
+            min-height: 45px;
+            > div {
+              padding: 12px 8px;
+              cursor: move;
+              height: 100%;
+            }
+            .ant-table-column-sorter {
+              position: relative;
+              display: inline-block;
+              width: 24px;
+              font-size: 12px;
+              color: #bfbfbf;
+              .anticon-caret-up {
+                position: relative;
+                left: 10px;
+                top: -3px;
+              }
+              .anticon-caret-down {
+                position: relative;
+                left: -2px;
+                top: 3px;
+              }
+            }
+            .edit {
+              position: absolute;
+              left: 0;
+              top: 0px;
+              cursor: pointer;
+              display: none;
+            }
+            .ant-checkbox-inner {
+              margin-top: 14px;
+              margin-left: calc(50% - 8px);
+            }
+          }
+          .page-card:hover {
+            .edit {
+              display: inline-block;
+            }
+          }
+          .page-card:not(:last-child) {
+            border-right: 1px solid #e8e8e8;
+          }
+        }
+      }
+      > .anticon-setting {
+        position: absolute;
+        font-size: 16px;
+        right: 10px;
+        top: 10px;
+      }
+    }
+  }
+  .setting:hover {
+    overflow-y: auto;
+  }
+  .setting::-webkit-scrollbar {
+    width: 7px;
+  }
+  .setting::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+    background: rgba(0, 0, 0, 0.13);
+  }
+  .setting::-webkit-scrollbar-track {
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+    border-radius: 3px;
+    border: 1px solid rgba(0, 0, 0, 0.07);
+    background: rgba(0, 0, 0, 0);
+  }
+  .ant-spin {
+    position: absolute;
+    margin-left: calc(50vw - 22px);
+    margin-top: 30vh;
+  }
+}
+
+.common-table-fields-modal {
+  .ant-modal {
+    top: 50px;
+    padding-bottom: 5px;
+    .ant-modal-body {
+      max-height: calc(100vh - 190px);
+      overflow-y: auto;
+      .ant-empty {
+        margin: 15vh 8px;
+      }
+    }
+    .ant-modal-body::-webkit-scrollbar {
+      width: 7px;
+    }
+    .ant-modal-body::-webkit-scrollbar-thumb {
+      border-radius: 5px;
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13);
+      background: rgba(0, 0, 0, 0.13);
+    }
+    .ant-modal-body::-webkit-scrollbar-track {
+      box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05);
+      border-radius: 3px;
+      border: 1px solid rgba(0, 0, 0, 0.07);
+      background: rgba(0, 0, 0, 0);
+    }
+  }
+}
diff --git a/src/components/sidemenu/comtableconfig/menuform/index.jsx b/src/templates/comtableconfig/menuform/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/menuform/index.jsx
rename to src/templates/comtableconfig/menuform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/menuform/index.scss b/src/templates/comtableconfig/menuform/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/menuform/index.scss
rename to src/templates/comtableconfig/menuform/index.scss
diff --git a/src/templates/comtableconfig/searchform/index.jsx b/src/templates/comtableconfig/searchform/index.jsx
new file mode 100644
index 0000000..1e08bf7
--- /dev/null
+++ b/src/templates/comtableconfig/searchform/index.jsx
@@ -0,0 +1,273 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Select, Icon, Radio, notification } from 'antd'
+import moment from 'moment'
+import EditTable from '../editable'
+import './index.scss'
+
+const { TextArea } = Input
+
+class MainSearch extends Component {
+  static propTpyes = {
+    dict: PropTypes.object, // 瀛楀吀椤�
+    formlist: PropTypes.any,
+    card: PropTypes.object
+  }
+
+  state = {
+    openType: null,
+    resourceType: null,
+    formlist: null
+  }
+
+  openTypeChange = (key, value) => {
+    if (key === 'type') {
+      let _options = ['label', 'field', 'initval', 'type', 'match']
+      if (value === 'select' && this.state.resourceType === '0') {
+        _options = [..._options, ...['resourceType', 'setAll', 'options', 'display']]
+      } else if (value === 'select' && this.state.resourceType === '1') {
+        _options = [..._options, ...['resourceType', 'setAll', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+      } else if (value === 'link' && this.state.resourceType === '0') {
+        _options = [..._options, ...['resourceType', 'setAll', 'options', 'linkField', 'display']]
+      } else if (value === 'link' && this.state.resourceType === '1') {
+        _options = [..._options, ...['resourceType', 'setAll', 'dataSource', 'linkField', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+      }
+      
+      this.setState({
+        openType: value,
+        formlist: this.state.formlist.map(form => {
+          form.hidden = !_options.includes(form.key)
+          return form
+        })
+      })
+    }
+  }
+
+  onChange = (e, key) => {
+    let value = e.target.value
+    if (key === 'resourceType') {
+      let _options = ['label', 'field', 'initval', 'type', 'match', 'resourceType', 'setAll']
+      if (this.state.openType === 'select' && value === '0') {
+        _options = [..._options, ...['options', 'display']]
+      } else if (this.state.openType === 'select' && value === '1') {
+        _options = [..._options, ...['dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+      } else if (this.state.openType === 'link' && value === '0') {
+        _options = [..._options, ...['options', 'linkField', 'display']]
+      } else if (this.state.openType === 'link' && value === '1') {
+        _options = [..._options, ...['dataSource', 'linkField', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+      }
+      
+      this.setState({
+        resourceType: value,
+        formlist: this.state.formlist.map(form => {
+          form.hidden = !_options.includes(form.key)
+          return form
+        })
+      })
+    }
+  }
+
+  getFields() {
+    const { getFieldDecorator } = this.props.form
+    const fields = []
+    this.state.formlist.forEach((item, index) => {
+      if (item.hidden) return
+
+      if (item.type === 'text') { // 鏂囨湰鎼滅储
+        let placeholder = ''
+        if (item.key === 'initval' && this.state.openType === 'date') {
+          placeholder = '渚嬶細' + moment().format('YYYY-MM-DD')
+        } else if (item.key === 'initval' && this.state.openType === 'datetime') {
+          placeholder = '渚嬶細' + moment().format('YYYY-MM-DD HH:mm:ss')
+        }
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal || '',
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<Input placeholder={placeholder} autoComplete="off" disabled={item.readonly} />)}
+            </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[2].toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  onChange={(value) => {this.openTypeChange(item.key, value)}}
+                  getPopupContainer={() => document.getElementById('commontable-search-form-box')}
+                >
+                  {item.options.map(option =>
+                    <Select.Option id={option.MenuID} title={option.text} key={option.MenuID} value={option.MenuID}>
+                      {item.key === 'icon' && <Icon type={option.text} />} {option.text}
+                    </Select.Option>
+                  )}
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'radio') {
+        fields.push(
+          <Col span={12} key={index}>
+            <Form.Item label={item.label}>
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.select'] + item.label + '!'
+                  }
+                ]
+              })(
+                <Radio.Group onChange={(e) => {this.onChange(e, item.key)}}>
+                  {
+                    item.options.map(option => {
+                      return (
+                        <Radio key={option.MenuID} value={option.MenuID}>{option.text}</Radio>
+                      )
+                    })
+                  }
+                </Radio.Group>,
+              )}
+            </Form.Item>
+          </Col>
+        )
+        
+      } else if (item.type === 'textarea') {
+        fields.push(
+          <Col span={20} offset={4} key={index}>
+            <Form.Item className="text-area">
+              {getFieldDecorator(item.key, {
+                initialValue: item.initVal,
+                rules: [
+                  {
+                    required: !!item.required,
+                    message: this.props.dict['form.required.input'] + item.label + '!'
+                  }
+                ]
+              })(<TextArea rows={4} />)}
+            </Form.Item>
+          </Col>
+        )
+      } else if (item.type === 'options') {
+        fields.push(
+          <Col span={20} offset={4} key={index}>
+            <EditTable data={item.initVal} type={this.state.openType} ref="editTable"/>
+          </Col>
+        )
+      }
+    })
+    return fields
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          let isvalid = true
+          values.id = this.props.card.id
+          values.uuid = this.props.card.uuid
+          // 涓嬫媺鑿滃崟鎴栧叧鑱旇彍鍗�
+          if ((values.type === 'select' || values.type === 'link') && values.resourceType === '0') {
+            values.options = this.refs.editTable.state.dataSource
+            values.dataSource = ''
+            let emptys = []
+            if (values.type === 'select') {
+              emptys = values.options.filter(op => !(op.Value && op.Text))
+            } else {
+              emptys = values.options.filter(op => !(op.Value && op.Text && op.ParentID))
+            }
+            if (emptys.length > 0) {
+              isvalid = false
+            }
+          } else if ((values.type === 'select' || values.type === 'link') && values.resourceType === '1') {
+            values.options = []
+          }
+
+          if (isvalid) {
+            resolve({
+              type: 'search',
+              values
+            })
+          } else {
+            notification.warning({
+              top: 92,
+              message: this.props.dict['header.form.selectItem.error'],
+              duration: 10
+            })
+          }
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  resetForm = (formlist) => {
+    if (!formlist) return
+    let type = formlist.filter(cell => cell.key === 'type')[0].initVal
+    let resourceType = formlist.filter(cell => cell.key === 'resourceType')[0].initVal
+    let _options = ['label', 'field', 'initval', 'type', 'match']
+    if (type === 'select' && resourceType === '0') {
+      _options = [..._options, ...['resourceType', 'setAll', 'options', 'display']]
+    } else if (type === 'select' && resourceType === '1') {
+      _options = [..._options, ...['resourceType', 'setAll', 'dataSource', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+    } else if (type === 'link' && resourceType === '0') {
+      _options = [..._options, ...['resourceType', 'setAll', 'options', 'linkField', 'display']]
+    } else if (type === 'link' && resourceType === '1') {
+      _options = [..._options, ...['resourceType', 'setAll', 'dataSource', 'linkField', 'valueField', 'valueText', 'orderBy', 'orderType', 'display']]
+    }
+    
+    this.setState({
+      openType: type,
+      resourceType: resourceType,
+      formlist: formlist.map(form => {
+        form.hidden = !_options.includes(form.key)
+        return form
+      })
+    })
+  }
+
+  UNSAFE_componentWillMount () {
+    this.resetForm(this.props.formlist)
+  }
+
+  render() {
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+    return (
+      <Form {...formItemLayout} className="ant-advanced-search-form commontable-search-form" id="commontable-search-form-box">
+        <Row gutter={24}>{this.getFields()}</Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(MainSearch)
\ No newline at end of file
diff --git a/src/components/sidemenu/comtableconfig/searchform/index.scss b/src/templates/comtableconfig/searchform/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/searchform/index.scss
rename to src/templates/comtableconfig/searchform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/settingform/index.jsx b/src/templates/comtableconfig/settingform/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/settingform/index.jsx
rename to src/templates/comtableconfig/settingform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/settingform/index.scss b/src/templates/comtableconfig/settingform/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/settingform/index.scss
rename to src/templates/comtableconfig/settingform/index.scss
diff --git a/src/templates/comtableconfig/source.jsx b/src/templates/comtableconfig/source.jsx
new file mode 100644
index 0000000..307604d
--- /dev/null
+++ b/src/templates/comtableconfig/source.jsx
@@ -0,0 +1,274 @@
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/comtable.js'
+import enUS from '@/locales/en-US/comtable.js'
+
+const CommonDict = (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS
+
+class CommonTableBaseData {
+  baseConfig = {
+    type: 'system',
+    setting: {
+      actionfixed: false,
+      columnfixed: false,
+      dataresource: ''
+    },
+    tables: [],
+    search: [
+      {
+        origin: true,
+        id: 0,
+        uuid: Utils.getuuid(),
+        label: 'text',
+        field: '',
+        initval: '',
+        type: 'text',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'like',
+        display: 'dropdown'
+      }, {
+        origin: true,
+        id: 1,
+        uuid: Utils.getuuid(),
+        label: 'select',
+        field: '',
+        initval: '',
+        type: 'select',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'equal',
+        display: 'dropdown'
+      }, {
+        origin: true,
+        id: 2,
+        uuid: Utils.getuuid(),
+        label: 'date',
+        field: '',
+        initval: '',
+        type: 'date',
+        resourceType: '0',
+        setAll: 'false',
+        options: [],
+        dataSource: '',
+        linkField: '',
+        valueField: '',
+        valueText: '',
+        orderBy: '',
+        orderType: 'asc',
+        match: 'greater',
+        display: 'dropdown'
+      }
+    ],
+    action: [
+      {
+        origin: true,
+        id: 0,
+        uuid: Utils.getuuid(),
+        label: 'add',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        outerFunc: '',
+        callbackFunc: '',
+        Ot: 'notRequired',
+        position: 'toolbar',
+        OpenType: 'pop',
+        pageTemplate: '',
+        icon: 'plus',
+        class: 'green'
+      }, {
+        origin: true,
+        id: 1,
+        uuid: Utils.getuuid(),
+        label: 'update',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        outerFunc: '',
+        callbackFunc: '',
+        Ot: 'requiredSgl',
+        position: 'grid',
+        OpenType: 'pop',
+        pageTemplate: '',
+        icon: 'form',
+        class: 'purple'
+      }, {
+        origin: true,
+        id: 2,
+        uuid: Utils.getuuid(),
+        label: 'delete',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        outerFunc: '',
+        callbackFunc: '',
+        Ot: 'required',
+        position: 'toolbar',
+        OpenType: 'prompt',
+        pageTemplate: '',
+        icon: 'delete',
+        class: 'red'
+      }, {
+        origin: true,
+        id: 3,
+        uuid: Utils.getuuid(),
+        label: 'freeze',
+        intertype: 'inner',
+        innerFunc: '',
+        interface: '',
+        outerFunc: '',
+        callbackFunc: '',
+        Ot: 'requiredOnce',
+        position: 'toolbar',
+        OpenType: 'exec',
+        pageTemplate: '',
+        icon: '',
+        class: 'default'
+      }
+    ],
+    columns: [
+      {
+        origin: true,
+        id: 0,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'fieldName1',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        id: 1,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'fieldName2',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        id: 2,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'fieldName3',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }, {
+        origin: true,
+        id: 3,
+        uuid: Utils.getuuid(),
+        Align: 'left',
+        label: 'fieldName4',
+        field: '',
+        Hide: 'false',
+        IsSort: 'true',
+        type: 'text',
+        Width: 120
+      }
+    ]
+  }
+
+  searchItems = [
+    {
+      type: 'search',
+      label: '鏂囨湰妗�',
+      subType: 'text',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '涓嬫媺妗�',
+      subType: 'select',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙澶╋級',
+      subType: 'date',
+      url: ''
+    },
+    {
+      type: 'search',
+      label: '鏃堕棿妗嗭紙绉掞級',
+      subType: 'datetime',
+      url: ''
+    }
+  ]
+
+  actionItems = [
+    {
+      type: 'action',
+      label: CommonDict['header.form.pop'],
+      subType: 'pop',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.prompt'],
+      subType: 'prompt',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.exec'],
+      subType: 'exec',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.tab'],
+      subType: 'tab',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.newpage'],
+      subType: 'newpage',
+      url: ''
+    },
+    {
+      type: 'action',
+      label: CommonDict['header.form.blank'],
+      subType: 'blank',
+      url: ''
+    }
+  ]
+
+  columnItems = [
+    {
+      type: 'columns',
+      label: CommonDict['header.form.text'],
+      subType: 'text',
+      url: ''
+    },
+    {
+      type: 'columns',
+      label: CommonDict['header.form.picture'],
+      subType: 'picture',
+      url: ''
+    }
+  ]
+}
+
+export default new CommonTableBaseData()
diff --git a/src/components/sidemenu/comtableconfig/actionform/index.jsx b/src/templates/modalconfig/actionform/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/actionform/index.jsx
rename to src/templates/modalconfig/actionform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/actionform/index.scss b/src/templates/modalconfig/actionform/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/actionform/index.scss
rename to src/templates/modalconfig/actionform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/columnform/index.jsx b/src/templates/modalconfig/columnform/index.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/columnform/index.jsx
copy to src/templates/modalconfig/columnform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/columnform/index.scss b/src/templates/modalconfig/columnform/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/columnform/index.scss
copy to src/templates/modalconfig/columnform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/dragelement/card.jsx b/src/templates/modalconfig/dragelement/card.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/dragelement/card.jsx
rename to src/templates/modalconfig/dragelement/card.jsx
diff --git a/src/components/sidemenu/comtableconfig/dragelement/index.jsx b/src/templates/modalconfig/dragelement/index.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/dragelement/index.jsx
copy to src/templates/modalconfig/dragelement/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/dragelement/index.scss b/src/templates/modalconfig/dragelement/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/dragelement/index.scss
copy to src/templates/modalconfig/dragelement/index.scss
diff --git a/src/components/sidemenu/comtableconfig/dragelement/itemtypes.js b/src/templates/modalconfig/dragelement/itemtypes.js
similarity index 100%
copy from src/components/sidemenu/comtableconfig/dragelement/itemtypes.js
copy to src/templates/modalconfig/dragelement/itemtypes.js
diff --git a/src/components/sidemenu/comtableconfig/dragelement/source.jsx b/src/templates/modalconfig/dragelement/source.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/dragelement/source.jsx
copy to src/templates/modalconfig/dragelement/source.jsx
diff --git a/src/components/sidemenu/comtableconfig/editable/index.jsx b/src/templates/modalconfig/editable/index.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/editable/index.jsx
copy to src/templates/modalconfig/editable/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/editable/index.scss b/src/templates/modalconfig/editable/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/editable/index.scss
copy to src/templates/modalconfig/editable/index.scss
diff --git a/src/components/sidemenu/comtableconfig/editcard/index.jsx b/src/templates/modalconfig/editcard/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/editcard/index.jsx
rename to src/templates/modalconfig/editcard/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/editcard/index.scss b/src/templates/modalconfig/editcard/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/editcard/index.scss
rename to src/templates/modalconfig/editcard/index.scss
diff --git a/src/components/sidemenu/comtableconfig/index.jsx b/src/templates/modalconfig/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/index.jsx
rename to src/templates/modalconfig/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/index.scss b/src/templates/modalconfig/index.scss
similarity index 100%
rename from src/components/sidemenu/comtableconfig/index.scss
rename to src/templates/modalconfig/index.scss
diff --git a/src/components/sidemenu/comtableconfig/menuform/index.jsx b/src/templates/modalconfig/menuform/index.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/menuform/index.jsx
copy to src/templates/modalconfig/menuform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/menuform/index.scss b/src/templates/modalconfig/menuform/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/menuform/index.scss
copy to src/templates/modalconfig/menuform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/searchform/index.jsx b/src/templates/modalconfig/searchform/index.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/searchform/index.jsx
rename to src/templates/modalconfig/searchform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/searchform/index.scss b/src/templates/modalconfig/searchform/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/searchform/index.scss
copy to src/templates/modalconfig/searchform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/settingform/index.jsx b/src/templates/modalconfig/settingform/index.jsx
similarity index 100%
copy from src/components/sidemenu/comtableconfig/settingform/index.jsx
copy to src/templates/modalconfig/settingform/index.jsx
diff --git a/src/components/sidemenu/comtableconfig/settingform/index.scss b/src/templates/modalconfig/settingform/index.scss
similarity index 100%
copy from src/components/sidemenu/comtableconfig/settingform/index.scss
copy to src/templates/modalconfig/settingform/index.scss
diff --git a/src/components/sidemenu/comtableconfig/source.jsx b/src/templates/modalconfig/source.jsx
similarity index 100%
rename from src/components/sidemenu/comtableconfig/source.jsx
rename to src/templates/modalconfig/source.jsx
diff --git a/src/utils/asyncLoadComponent.jsx b/src/utils/asyncLoadComponent.jsx
new file mode 100644
index 0000000..74929c1
--- /dev/null
+++ b/src/utils/asyncLoadComponent.jsx
@@ -0,0 +1,32 @@
+import React, {Component} from 'react'
+import { Spin } from 'antd'
+
+/**
+ * @description 寮傛鍔犺浇妯″潡
+ * @param {*} importComponent
+ */
+export default function asyncComponent(importComponent) {
+  return class extends Component {
+    constructor(props) {
+      super(props)
+
+      this.state = {
+        component: null
+      }
+    }
+
+    async componentDidMount() {
+      const {default: component} = await importComponent()
+
+      this.setState({component})
+    }
+
+    render() {
+      const C = this.state.component
+
+      return C ?
+        <C {...this.props} /> :
+        <Spin style={{position: 'fixed', left: 'calc(50vw - 22px)', top: 'calc(50vh - 70px)'}} size="large" />
+    }
+  }
+}
\ No newline at end of file

--
Gitblit v1.8.0