From 0f75cd54d62aa6d623ff024ca787c85a578a5f38 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期二, 15 九月 2020 11:09:40 +0800
Subject: [PATCH] 2020-09-15

---
 src/menu/components/tabs/tabsetting/settingform/index.scss |   24 +
 src/menu/searchcomponent/index.scss                        |    2 
 src/assets/mobimg/bar.png                                  |    0 
 src/menu/components/tabs/tablabelform/index.jsx            |   86 +++++
 src/menu/components/tabs/antv-tabs/index.scss              |   61 +++
 src/menu/components/chart/antv-bar/index.scss              |    9 
 /dev/null                                                  |  201 ------------
 src/menu/components/chart/antv-bar/index.jsx               |    6 
 src/menu/modelsource/option.jsx                            |    2 
 src/assets/mobimg/bar1.png                                 |    0 
 src/tabviews/custom/index.jsx                              |   14 
 src/menu/menushell/card.jsx                                |    7 
 src/menu/components/tabs/tabsetting/index.jsx              |   80 +++++
 src/menu/components/tabs/tabsetting/index.scss             |   94 +++++
 src/menu/components/tabs/antv-tabs/index.jsx               |  224 ++++++++++++++
 src/menu/menushell/index.jsx                               |    7 
 src/assets/mobimg/mob-login1.png                           |    0 
 src/assets/mobimg/tabs.png                                 |    0 
 src/menu/components/tabs/tablabelform/index.scss           |    0 
 src/menu/menushell/index.scss                              |    4 
 src/assets/css/main.scss                                   |    8 
 src/menu/components/tabs/tabsetting/settingform/index.jsx  |  127 +++++++
 22 files changed, 733 insertions(+), 223 deletions(-)

diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index 8fa787e..c6ec9d6 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -304,6 +304,14 @@
         color: purple;
       }
     }
+    .mk-popover-control::after {
+      position: absolute;
+      content: ' ';
+      width: 100%;
+      height: 10px;
+      bottom: -10px;
+      left: 0px;
+    }
     .ant-popover-inner-content {
       padding: 5px 20px;
     }
diff --git a/src/assets/mobimg/bar.png b/src/assets/mobimg/bar.png
index 36674af..a7a3907 100644
--- a/src/assets/mobimg/bar.png
+++ b/src/assets/mobimg/bar.png
Binary files differ
diff --git a/src/assets/mobimg/bar1.png b/src/assets/mobimg/bar1.png
index c4168b9..bd618ab 100644
--- a/src/assets/mobimg/bar1.png
+++ b/src/assets/mobimg/bar1.png
Binary files differ
diff --git a/src/assets/mobimg/mob-login1.png b/src/assets/mobimg/mob-login1.png
index 9d4e94f..1ecd0c4 100644
--- a/src/assets/mobimg/mob-login1.png
+++ b/src/assets/mobimg/mob-login1.png
Binary files differ
diff --git a/src/assets/mobimg/tabs.png b/src/assets/mobimg/tabs.png
new file mode 100644
index 0000000..5c44839
--- /dev/null
+++ b/src/assets/mobimg/tabs.png
Binary files differ
diff --git a/src/menu/components/chart/antv-bar/index.jsx b/src/menu/components/chart/antv-bar/index.jsx
index 417665f..d6c61c0 100644
--- a/src/menu/components/chart/antv-bar/index.jsx
+++ b/src/menu/components/chart/antv-bar/index.jsx
@@ -20,15 +20,12 @@
   static propTpyes = {
     config: PropTypes.object,
     card: PropTypes.object,
-    editId: PropTypes.any,
-    triggerEdit: PropTypes.func,
     updateConfig: PropTypes.func,
   }
 
   state = {
     dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    card: null,
-    visible: true
+    card: null
   }
 
   UNSAFE_componentWillMount () {
@@ -81,6 +78,7 @@
       let _card = {
         uuid: card.uuid,
         type: card.type,
+        floor: card.floor,
         format: 'array',   // 缁勪欢灞炴�� - 鏁版嵁鏍煎紡
         pageable: false,   // 缁勪欢灞炴�� - 鏄惁鍙垎椤�
         switchable: false, // 缁勪欢灞炴�� - 鏁版嵁鏄惁鍙垏鎹�
diff --git a/src/menu/components/chart/antv-bar/index.scss b/src/menu/components/chart/antv-bar/index.scss
index e96a3a6..39a775e 100644
--- a/src/menu/components/chart/antv-bar/index.scss
+++ b/src/menu/components/chart/antv-bar/index.scss
@@ -1,7 +1,7 @@
 .menu-line-chart-edit-box {
   position: relative;
   // margin-bottom: 0px;
-  border: 1px solid #e8e8e8;
+  box-sizing: border-box;
   
   .canvas {
     margin: 0px;
@@ -9,14 +9,14 @@
   }
 
   .chart-header {
-    height: 50px;
+    height: 45px;
     border-bottom: 1px solid #e8e8e8;
     overflow: hidden;
 
     .chart-title {
       font-size: 16px;
       float: left;
-      line-height: 50px;
+      line-height: 45px;
       margin-left: 10px;
     }
   }
@@ -36,3 +36,6 @@
     }
   }
 }
+.menu-line-chart-edit-box:hover {
+  box-shadow: 0px 0px 2px #e8e8e8;
+}
diff --git a/src/menu/components/chart/mob-login-2/index.jsx b/src/menu/components/chart/mob-login-2/index.jsx
deleted file mode 100644
index 37e1952..0000000
--- a/src/menu/components/chart/mob-login-2/index.jsx
+++ /dev/null
@@ -1,423 +0,0 @@
-import React, {Component} from 'react'
-import PropTypes from 'prop-types'
-import { is, fromJS } from 'immutable'
-import { InputItem, Button } from 'antd-mobile'
-import { Icon } from 'antd'
-
-import zhCN from '@/locales/zh-CN/mob.js'
-import enUS from '@/locales/en-US/mob.js'
-import Utils from '@/utils/utils.js'
-import ContentUpdate from '@/mob/contupdate'
-import ContentDelete from '@/mob/contdelete'
-import './index.scss'
-
-class MobLogin2 extends Component {
-  static propTpyes = {
-    card: PropTypes.object,
-    editId: PropTypes.any,
-    triggerEdit: PropTypes.func,
-    updateConfig: PropTypes.func,
-    onDoubleClick: PropTypes.func
-  }
-
-  state = {
-    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
-    view: 'account',
-    param: {
-      type: 'login',
-      subtype: 'mob-login-2',
-      box: { uuid: Utils.getuuid(), eleType: 'box', style: {}},
-      title: {
-        uuid: Utils.getuuid(), eleType: 'text', content: '鐧诲綍',
-        style: {
-          fontSize: '18px', fontWeight: 'bold', color: '#000000', textAlign: 'center', marginTop: '10vh', marginBottom: '10vh'
-        }
-      },
-      user: { uuid: Utils.getuuid(), eleType: 'input', content: '閭/鎵嬫満', style: {}},
-      password: { uuid: Utils.getuuid(), eleType: 'input', content: '瀵嗙爜', style: {}},
-      login: {
-        uuid: Utils.getuuid(), eleType: 'button', content: '鐧诲綍',
-        style: {
-          fontSize: '16px', color: '#ffffff', textAlign: 'center', lineHeight: 2.4, backgroundColor: '#44a8f2'
-        }
-      },
-      phone: {
-        uuid: Utils.getuuid(), eleType: 'button', content: '鎵嬫満鐭俊鐧诲綍',
-        style: {
-          fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2'
-        }
-      },
-      register: {
-        uuid: Utils.getuuid(), eleType: 'text', content: '娉ㄥ唽',
-        style: {
-          fontSize: '14px', color: '#44a8f2', textAlign: 'left'
-        }
-      },
-      lose: {
-        uuid: Utils.getuuid(), eleType: 'text', content: '蹇樿瀵嗙爜锛�',
-        style: {
-          fontSize: '14px', color: '#44a8f2', textAlign: 'right', textDecoration: 'underline'
-        }
-      },
-      auth: {
-        uuid: Utils.getuuid(), eleType: 'text', content: '鍏朵粬鐧诲綍鏂瑰紡',
-        style: {
-          fontSize: '14px', color: '#bcbcbc', textAlign: 'center', marginTop: '30px', marginBottom: '20px'
-        }
-      },
-      authlist: {
-        uuid: Utils.getuuid(),
-        subItems: [
-          {uuid: 'qq', type: 'qq', icon: 'qq', label: 'QQ'},
-          {uuid: 'wechat', type: 'wechat', icon: 'wechat', label: '寰俊'},
-        ],
-      },
-      copyright: {
-        uuid: Utils.getuuid(), eleType: 'textarea', content: 'Copyright漏2017  鎵�鏈夌浉鍏崇増鏉冨綊  鍖椾含鏄庣鏅崕淇℃伅鎶�鏈湁闄愬叕鍙�',
-        style: {
-          fontSize: '12px', textAlign: 'center', color: 'rgba(0, 0, 0, 0.65)'
-        }
-      },
-      links: {
-        uuid: Utils.getuuid(), eleType: 'link', substyle: false,
-        subItems: [
-          {eleType: 'link', content: '闅愮鏀跨瓥', url: '', uuid: Utils.getuuid()},
-          {eleType: 'link', content: '浣跨敤鏉℃', url: '', uuid: Utils.getuuid()},
-        ],
-        style: {
-          fontSize: '12px', textAlign: 'center', color: '#44a8f2', textDecoration: 'underline'
-        }
-      },
-      account: {
-        uuid: Utils.getuuid(), eleType: 'button', content: '璐﹀彿瀵嗙爜鐧诲綍',
-        style: {
-          fontSize: '16px', color: '#44a8f2', textAlign: 'center', lineHeight: 2.4, border: '1px solid #44a8f2'
-        }
-      },
-    }
-  }
-
-  UNSAFE_componentWillMount () {
-    const { card } = this.props
-    const { param } = this.state
-
-    if (!card.box) {
-      this.props.updateConfig({...param, ...card})
-    }
-  }
-
-  shouldComponentUpdate (nextProps, nextState) {
-    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
-  }
-
-  editTitle = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.title.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.title.uuid,
-      items: ['font', 'margin'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editPlaceholder = (e, type) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      componentId: card.uuid,
-      uuid: card[type].uuid,
-      items: [''],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editMsg = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.copyright.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.copyright.uuid,
-      items: ['font', 'margin'],
-    }
-    this.props.triggerEdit(element)
-  }
-  
-  editLinks = (e, item) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.links.style).toJS(),
-      componentId: card.uuid,
-      classId: card.links.uuid,
-      uuid: item.uuid,
-      items: ['font'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editLogin = (e, type) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card[type].style).toJS(),
-      componentId: card.uuid,
-      uuid: card[type].uuid,
-      items: ['font', 'background', 'border', 'margin']
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editLose = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.lose.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.lose.uuid,
-      items: ['font'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editRegister = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.register.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.register.uuid,
-      items: ['font'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editAuth = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.auth.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.auth.uuid,
-      items: ['font', 'margin'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  editBox = (e) => {
-    const { card } = this.props
-    e.stopPropagation()
-    let element = {
-      ...fromJS(card.box.style).toJS(),
-      componentId: card.uuid,
-      uuid: card.box.uuid,
-      items: ['font', 'padding', 'background'],
-    }
-    this.props.triggerEdit(element)
-  }
-
-  linkItemAdd = (e) => {
-    let card = fromJS(this.props.card).toJS()
-    e.stopPropagation()
-
-    card.links.subItems.push({
-      eleType: 'link',
-      content: 'link',
-      url: '',
-      uuid: Utils.getuuid()
-    })
-
-    this.props.updateConfig(card)
-  }
-
-  updateContent = (card) => {
-    this.props.updateConfig(card)
-  }
-
-  updateLinkItem = (val, item) => {
-    let card = fromJS(this.props.card).toJS()
-
-    if (!val) {
-      card.links.subItems = card.links.subItems.filter(cell => cell.uuid !== item.uuid)
-    } else {
-      card.links.subItems = card.links.subItems.map(cell => {
-        if (cell.uuid === item.uuid) {
-          return val
-        } else {
-          return cell
-        }
-      })
-    }
-
-    this.props.updateConfig(card)
-  }
-
-  render () {
-    const { card, editId } = this.props
-    const { view } = this.state
-
-    if (!card.box) return null
-
-    let titleStyle = card.title && card.title.style ? fromJS(card.title.style).toJS() : null
-    if (titleStyle && titleStyle.marginTop && /vh$/ig.test(titleStyle.marginTop)) {
-      let percent = parseInt(titleStyle.marginTop)
-      titleStyle.marginTop = `calc(${(percent / 100) * 615}px)`
-    }
-    if (titleStyle && titleStyle.marginBottom && /vh$/ig.test(titleStyle.marginBottom)) {
-      let percent = parseInt(titleStyle.marginBottom)
-      titleStyle.marginBottom = `calc(${(percent / 100) * 615}px)`
-    }
-
-    if (view === 'account') {
-      return (
-        <div className="mob-login-2" onClick={this.editBox} style={card.box.style}>
-          {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}>
-            <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/>
-            {card.title.content}
-          </div> : null}
-          
-          <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}>
-            <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/>
-            <InputItem disabled={true} placeholder={card.user.content}></InputItem>
-          </div>
-          <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}>
-            <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/>
-            <InputItem disabled={true} placeholder={card.password.content}></InputItem>
-          </div>
-          <Button 
-            className={'login ' + (editId === card.login.uuid ? 'editing' : '')} 
-            onDoubleClick={() => this.props.doubleClickCard(card.login)}
-            style={card.login.style}
-            onClick={(e) => this.editLogin(e, 'login')}
-          >
-            <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/>
-            {card.login.content}
-          </Button>
-          <Button 
-            className={'login ' + (editId === card.phone.uuid ? 'editing' : '')} 
-            onDoubleClick={() => this.setState({view: 'phone'})}
-            style={card.phone.style}
-            onClick={(e) => this.editLogin(e, 'phone')}
-          >
-            <ContentUpdate element={card.phone} updateContent={(ele) => this.updateContent({...card, phone: ele})}/>
-            {card.phone.content}
-          </Button>
-          <div className="row-box">
-            {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}>
-              <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/>
-              {card.register.content}
-            </div> : null}
-            {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}>
-              <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/>
-              {card.lose.content}
-            </div> : null}
-            <div style={{clear: 'both'}}></div>
-          </div>
-          {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}>
-            <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/>
-            {card.auth.content}
-          </div> : null}
-          {card.authlist ? <div className="other-auth">
-            {card.authlist.subItems.map(cell => (
-              <span className="deletable-item" key={cell.type}>
-                <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/>
-                <Icon type={cell.icon} />
-                <p>{cell.label}</p>
-              </span>
-            ))}
-          </div> : null}
-          {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}>
-            <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/>
-            {card.copyright.content}
-          </div> : null}
-          {card.links ? <div className="links" style={card.links.style}>
-            {card.links.subItems.map(item => (
-              <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}>
-                <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/>
-                {item.content}
-              </span>
-            ))}
-            <Icon type="plus" onClick={this.linkItemAdd} />
-          </div> : null}
-        </div>
-      )
-    } else if (view === 'phone') {
-      return (
-        <div className="mob-login-2" onClick={this.editBox} style={card.box.style}>
-          {card.title ? <div className={'plat-name ' + (editId === card.title.uuid ? 'editing' : '')} style={titleStyle} onClick={this.editTitle}>
-            <ContentUpdate element={card.title} updateContent={(ele) => this.updateContent({...card, title: ele})}/>
-            {card.title.content}
-          </div> : null}
-          
-          <div className={`mk-login-input ${editId === card.user.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'user')}>
-            <ContentUpdate element={card.user} deletable={false} updateContent={(ele) => this.updateContent({...card, user: ele})}/>
-            <InputItem disabled={true} placeholder={card.user.content}></InputItem>
-          </div>
-          <div className={`mk-login-input ${editId === card.password.uuid ? 'editing' : ''}`} onClick={(e) => this.editPlaceholder(e, 'password')}>
-            <ContentUpdate element={card.password} deletable={false} updateContent={(ele) => this.updateContent({...card, password: ele})}/>
-            <InputItem disabled={true} placeholder={card.password.content}></InputItem>
-          </div>
-          <Button 
-            className={'login ' + (editId === card.login.uuid ? 'editing' : '')} 
-            onDoubleClick={() => this.props.doubleClickCard(card.login)}
-            style={card.login.style}
-            onClick={(e) => this.editLogin(e, 'login')}
-          >
-            <ContentUpdate element={card.login} deletable={false} updateContent={(ele) => this.updateContent({...card, login: ele})}/>
-            {card.login.content}
-          </Button>
-          <Button 
-            className={'login ' + (editId === card.account.uuid ? 'editing' : '')} 
-            onDoubleClick={() => this.setState({view: 'account'})}
-            style={card.account.style}
-            onClick={(e) => this.editLogin(e, 'account')}
-          >
-            <ContentUpdate element={card.account} updateContent={(ele) => this.updateContent({...card, account: ele})}/>
-            {card.account.content}
-          </Button>
-          <div className="row-box">
-            {card.register ? <div className={'col-item ' + (editId === card.register.uuid ? 'editing' : '')} style={card.register.style} onClick={this.editRegister}>
-              <ContentUpdate element={card.register} updateContent={(ele) => this.updateContent({...card, register: ele})}/>
-              {card.register.content}
-            </div> : null}
-            {card.lose ? <div className={'col-item right ' + (editId === card.lose.uuid ? 'editing' : '')} style={card.lose.style} onClick={this.editLose}>
-              <ContentUpdate element={card.lose} updateContent={(ele) => this.updateContent({...card, lose: ele})}/>
-              {card.lose.content}
-            </div> : null}
-            <div style={{clear: 'both'}}></div>
-          </div>
-          {card.auth ? <div className={'plat-name ' + (editId === card.auth.uuid ? 'editing' : '')} style={card.auth.style} onClick={this.editAuth}>
-            <ContentUpdate element={card.auth} updateContent={(ele) => this.updateContent({...card, auth: ele})}/>
-            {card.auth.content}
-          </div> : null}
-          {card.authlist ? <div className="other-auth">
-            {card.authlist.subItems.map(cell => (
-              <span className="deletable-item" key={cell.type}>
-                <ContentDelete element={cell} list={card.authlist} updateContent={(ele) => this.updateContent({...card, authlist: ele})}/>
-                <Icon type={cell.icon} />
-                <p>{cell.label}</p>
-              </span>
-            ))}
-          </div> : null}
-          {card.copyright ? <div className={'company-msg ' + (editId === card.copyright.uuid ? 'editing' : '')} style={card.copyright.style} onClick={this.editMsg}>
-            <ContentUpdate element={card.copyright} updateContent={(ele) => this.updateContent({...card, copyright: ele})}/>
-            {card.copyright.content}
-          </div> : null}
-          {card.links ? <div className="links" style={card.links.style}>
-            {card.links.subItems.map(item => (
-              <span className={(editId === item.uuid ? 'editing' : '')} key={item.uuid} onClick={(e) => this.editLinks(e, item)}>
-                <ContentUpdate element={item} updateContent={(val) => this.updateLinkItem(val, item)}/>
-                {item.content}
-              </span>
-            ))}
-            <Icon type="plus" onClick={this.linkItemAdd} />
-          </div> : null}
-        </div>
-      )
-    }
-  }
-}
-
-export default MobLogin2
\ No newline at end of file
diff --git a/src/menu/components/chart/mob-login-2/index.scss b/src/menu/components/chart/mob-login-2/index.scss
deleted file mode 100644
index 59cd1e1..0000000
--- a/src/menu/components/chart/mob-login-2/index.scss
+++ /dev/null
@@ -1,201 +0,0 @@
-.mob-login-2 {
-  position: relative;
-  width: 100%;
-  min-height: 100%;
-  overflow-x: hidden;
-  background-repeat: no-repeat;
-  background-size: cover;
-  background-position: center center;
-
-  .plat-name {
-    position: relative;
-    max-width: 280px;
-    min-height: 10px;
-    margin: 0 auto;
-    text-align: center;
-    line-height: 1.5;
-    font-size: 18px;
-    color: #ffffff;
-    border: 1px dotted transparent;
-  }
-  .plat-name.editing {
-    border: 1px solid #1890ff;
-    box-shadow: 0px 0px 2px #1890ff;
-  }
-  .plat-name:not(.editing):hover {
-    border-color: #535353;
-  }
-  .row-box {
-    position: relative;
-    width: 280px;
-    margin: 0 auto;
-    line-height: 1.5;
-
-    .col-item {
-      position: relative;
-      display: inline-block;
-      width: 50%;
-      border: 1px dotted transparent;
-    }
-    .col-item.right {
-      float: right;
-    }
-
-    .col-item.editing {
-      border: 1px solid #1890ff;
-      box-shadow: 0px 0px 2px #1890ff;
-    }
-    .col-item:not(.editing):hover {
-      border-color: #535353;
-    }
-  }
-  .other-auth {
-    text-align: center;
-    font-size: 26px;
-    color: rgb(68, 168, 242);
-
-    span {
-      position: relative;
-      display: inline-block;
-      vertical-align: top;
-      p {
-        font-size: 12px;
-        margin-bottom: 10px;
-      }
-    }
-    span:not(:last-child) {
-      margin-right: 15px;
-    }
-  }
-
-  .am-list-item {
-    position: relative;
-    z-index: 1;
-    width: 100%;
-    font-size: 14px;
-    height: 38px;
-    min-height: 38px;
-    line-height: 1.5;
-    margin-bottom: 10px;
-    border: 1px solid #dddddd;
-
-    .am-input-control input:disabled {
-      color: rgba(0, 0, 0, 0.65);
-    }
-
-    .am-input-label {
-      width: 30px;
-      color: inherit;
-      padding-top: 10px;
-    }
-    input {
-      font-size: 14px;
-      color: inherit;
-    }
-    input::-webkit-input-placeholder {
-      color: inherit;
-      opacity: 0.5;
-    }
-    input:-moz-placeholder {
-      color: inherit;
-      opacity: 0.5;
-    }
-    input::-moz-placeholder {
-      color: inherit;
-      opacity: 0.5;
-    }
-    input:-ms-input-placeholder {
-      color: inherit;
-      opacity: 0.5;
-    }
-  }
-  .am-list-item:not(:last-child) .am-list-line {
-    border: none;
-  }
-
-  .mk-login-input {
-    width: 280px;
-    position: relative;
-    margin: 0 auto;
-  }
-  
-  .am-button {
-    position: relative;
-    z-index: 1;
-    width: 280px;
-    margin: 0 auto 10px;
-    border: 1px dotted transparent;
-    overflow: visible;
-    letter-spacing: 0px;
-    background-repeat: no-repeat;
-    background-size: cover;
-    background-position: center center;
-    border-radius: 0;
-    
-    span {
-      font-style: inherit;
-      font-weight: inherit;
-    }
-  }
-  .am-button:hover {
-    color: unset;
-    border-color: #535353;
-  }
-  .company-msg {
-    width: 88%;
-    min-height: 10px;
-    margin-left: 6%;
-    font-size: 12px;
-    text-align: center;
-    line-height: 1.5;
-    letter-spacing: 0px;
-    border: 1px dotted transparent;
-  }
-  .company-msg.editing {
-    border: 1px solid #1890ff;
-    box-shadow: 0px 0px 2px #1890ff;
-  }
-  .company-msg:not(.editing):hover {
-    border-color: #535353;
-  }
-
-  .links {
-    min-height: 10px;
-    font-size: 12px;
-    text-align: center;
-    line-height: 1.5;
-
-    span {
-      display: inline-block;
-      position: relative;
-      text-decoration: inherit;
-      font-style: inherit;
-      min-width: 40px;
-      border: 1px dotted transparent;
-    }
-    span:not(:last-child) {
-      margin-right: 10px;
-    }
-    span:hover {
-      border-color: #535353;
-    }
-    span.editing {
-      border: 1px solid #1890ff;
-      box-shadow: 0px 0px 2px #1890ff;
-    }
-    >.anticon-plus {
-      cursor: pointer;
-      color: #26C281;
-    }
-  }
-}
-.am-picker-popup-wrap {
-  left: calc(50vw - 305px);
-  right: calc(50vw - 45px);
-  bottom: 54px;
-  overflow: hidden;
-}
-.clear-both {
-  float: none!important;
-  clear: both;
-}
\ No newline at end of file
diff --git a/src/menu/components/tabs/antv-tabs/index.jsx b/src/menu/components/tabs/antv-tabs/index.jsx
new file mode 100644
index 0000000..77d9ed6
--- /dev/null
+++ b/src/menu/components/tabs/antv-tabs/index.jsx
@@ -0,0 +1,224 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Tabs, Icon, Popover, Modal } from 'antd'
+
+import asyncComponent from '@/utils/asyncComponent'
+
+import Utils from '@/utils/utils.js'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import './index.scss'
+
+const SettingComponent = asyncComponent(() => import('../tabsetting'))
+const TabLabelComponent = asyncComponent(() => import('../tablabelform'))
+
+const { TabPane } = Tabs
+const { confirm } = Modal
+
+class antvBarLineChart extends Component {
+  static propTpyes = {
+    config: PropTypes.object,
+    tabs: PropTypes.object,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    tabs: null,
+    editab: null,
+    labelvisible: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { tabs, config } = this.props
+
+    if (tabs.isNew) {
+      let name = ''
+      let i = 1
+      
+      while (!name) {
+        let _name = '鏍囩椤�' + i
+        if (config.components.filter(com => com.setting && com.setting.name === _name).length === 0) {
+          name = _name
+        }
+        i++
+      }
+
+      let _tabs = {
+        uuid: tabs.uuid,
+        type: tabs.type,
+        floor: tabs.floor,
+        subtype: tabs.subtype,
+        setting: {span: 12, position: 'top', tabStyle: 'line', name},
+        subtabs: [{
+          uuid: Utils.getuuid(),
+          label: 'Tab 1',
+          icon: '',
+          subcomponents: [],
+        }, {
+          uuid: Utils.getuuid(),
+          label: 'Tab 2',
+          icon: '',
+          subcomponents: [],
+        }, {
+          uuid: Utils.getuuid(),
+          label: 'Tab 3',
+          icon: '',
+          subcomponents: [],
+        }]
+      }
+      this.setState({
+        tabs: _tabs
+      })
+      this.props.updateConfig(_tabs)
+    } else {
+      this.setState({
+        tabs: fromJS(tabs).toJS()
+      })
+    }
+  }
+
+  componentDidMount () { }
+
+  UNSAFE_componentWillReceiveProps (nextProps) {
+    if (!is(fromJS(this.props.plot), fromJS(nextProps.plot))) {
+
+    }
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  updateComponent = (component) => {
+    
+    this.setState({
+      tabs: component
+    })
+    this.props.updateConfig(component)
+  }
+
+  tabAdd = (e) => {
+    e.stopPropagation()
+    this.setState({
+      editab: {
+        uuid: '',
+        label: '',
+        icon: '',
+        subcomponents: []
+      },
+      labelvisible: true
+    })
+  }
+
+  editTab = (tab) => {
+    this.setState({
+      editab: tab,
+      labelvisible: true
+    })
+  }
+
+  tabLabelSubmit = () => {
+    let tabs = fromJS(this.state.tabs).toJS()
+    let editab = fromJS(this.state.editab).toJS()
+
+    this.tabLabelRef.handleConfirm().then(res => {
+      editab.label = res.label
+      editab.icon = res.icon
+
+      if (editab.uuid) {
+        tabs.subtabs = tabs.subtabs.map(t => {
+          if (t.uuid === editab.uuid) {
+            return editab
+          } else {
+            return t
+          }
+        })
+      } else {
+        editab.uuid = Utils.getuuid()
+        tabs.subtabs.push(editab)
+      }
+
+      this.setState({
+        editab: null,
+        labelvisible: false,
+        tabs
+      })
+      this.props.updateConfig(tabs)
+    })
+  }
+
+  delTab = (tab) => {
+    let tabs = fromJS(this.state.tabs).toJS()
+    const _this = this
+
+    tabs.subtabs = tabs.subtabs.filter(t => t.uuid !== tab.uuid)
+
+    confirm({
+      title: '纭畾鍒犻櫎鏍囩锛�',
+      content: '',
+      onOk() {
+        _this.setState({tabs})
+        _this.props.updateConfig(tabs)
+      },
+      onCancel() {}
+    })
+  }
+
+  moveSwitch = (index, index1) => {
+    let tabs = fromJS(this.state.tabs).toJS()
+    tabs.subtabs[index] = tabs.subtabs.splice(index1, 1, tabs.subtabs[index])[0]
+
+    this.setState({tabs})
+    this.props.updateConfig(tabs)
+  }
+
+  render() {
+    const { tabs, dict, labelvisible, editab } = this.state
+
+    return (
+      <div className="menu-tabs-edit-box">
+        <SettingComponent config={tabs} updateConfig={this.updateComponent} />
+        <Tabs defaultActiveKey="1" tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
+          {tabs.subtabs.map((tab, index) => (
+            <TabPane tab={
+              <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+                <div className="mk-popover-control">
+                  <Icon className="edit" title="edit" type="edit" onClick={() => this.editTab(tab)} />
+                  {index !== 0 ? <Icon className="edit" type="arrow-left" onClick={() => this.moveSwitch(index, index - 1)} /> : null}
+                  {(index + 1) !== tabs.subtabs.length ? <Icon className="edit" type="arrow-right" onClick={() => this.moveSwitch(index, index + 1)} /> : null}
+                  <Icon className="close" title="delete" type="close" onClick={() => this.delTab(tab)} />
+                </div>
+              } trigger="hover">
+                <span>{tab.icon ? <Icon type={tab.icon} /> : null}{tab.label}</span>
+              </Popover>
+            } key={tab.uuid}>
+              Content of Tab Pane {tab.label}
+            </TabPane>
+          ))}
+          <TabPane className="tab-add" disabled tab={<Icon onClick={this.tabAdd} type="plus" />} key="add"></TabPane>
+        </Tabs>
+        <Modal
+          wrapClassName="popview-modal"
+          title={'鏍囩缂栬緫'}
+          visible={labelvisible}
+          width={600}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.tabLabelSubmit}
+          onCancel={() => { this.setState({ labelvisible: false }) }}
+          destroyOnClose
+        >
+          <TabLabelComponent
+            dict={dict}
+            tab={editab}
+            wrappedComponentRef={(inst) => this.tabLabelRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default antvBarLineChart
\ No newline at end of file
diff --git a/src/menu/components/tabs/antv-tabs/index.scss b/src/menu/components/tabs/antv-tabs/index.scss
new file mode 100644
index 0000000..7f1b561
--- /dev/null
+++ b/src/menu/components/tabs/antv-tabs/index.scss
@@ -0,0 +1,61 @@
+.menu-tabs-edit-box {
+  position: relative;
+  box-sizing: border-box;
+
+  .ant-tabs-tabpane-active {
+    min-height: 200px;
+  }
+  .ant-tabs .ant-tabs-left-bar .ant-tabs-tab {
+    padding: 0px;
+    text-align: right;
+    > span {
+      display: inline-block;
+      padding: 8px 24px;
+    }
+    .anticon-plus {
+      padding: 8px 24px;
+    }
+  }
+  .ant-tabs .ant-tabs-right-bar .ant-tabs-tab {
+    padding: 0px;
+    text-align: left;
+    > span {
+      display: inline-block;
+      padding: 8px 24px;
+    }
+    .anticon-plus {
+      padding: 8px 24px;
+    }
+  }
+  .ant-tabs-tab {
+    padding: 0px;
+    text-align: center;
+    > span {
+      display: inline-block;
+      padding: 12px 16px;
+    }
+    .anticon-plus {
+      color: #26C281;
+      padding: 12px 16px;
+      margin-right: 0px;
+      min-width: 100%;
+      cursor: pointer;
+    }
+  }
+  .ant-tabs-bottom .ant-tabs-bottom-bar .ant-tabs-ink-bar {
+    top: 0px;
+  }
+  .ant-tabs-card {
+    .ant-tabs-card-bar .ant-tabs-tab:last-child {
+      padding: 0px;
+      border: 0px;
+      background: transparent;
+      .anticon-plus {
+        padding: 12px 16px;
+      }
+    }
+  }
+}
+.menu-tabs-edit-box:hover {
+  box-shadow: 0px 0px 2px #e8e8e8;
+}
diff --git a/src/menu/components/tabs/tablabelform/index.jsx b/src/menu/components/tabs/tablabelform/index.jsx
new file mode 100644
index 0000000..dedf405
--- /dev/null
+++ b/src/menu/components/tabs/tablabelform/index.jsx
@@ -0,0 +1,86 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Icon, Select } from 'antd'
+
+// import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,   // 瀛楀吀椤�
+    tab: PropTypes.object,    // 鏁版嵁婧愰厤缃�
+  }
+
+  state = {}
+
+  UNSAFE_componentWillMount () {
+
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+
+  render() {
+    const { tab } = this.props
+    const { getFieldDecorator } = this.props.form
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 12 }
+      }
+    }
+
+    return (
+      <Form {...formItemLayout}>
+        <Row gutter={24}>
+          <Col span={24}>
+            <Form.Item label="鍚嶇О">
+              {getFieldDecorator('label', {
+                initialValue: tab.label,
+                rules: [
+                  {
+                    required: true,
+                    message: this.props.dict['form.required.input'] + '鍚嶇О!'
+                  }
+                ]
+              })(<Input placeholder={''} autoComplete="off" />)}
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item label="鍥炬爣">
+              {getFieldDecorator('icon', {
+                initialValue: tab.icon || ''
+              })(
+                <Select>
+                  <Select.Option key="empty" value=""> 鏃� </Select.Option>
+                  <Select.Option key="android" value="android"> <Icon type="android" /> </Select.Option>
+                  <Select.Option key="apple" value="apple"> <Icon type="apple" /> </Select.Option>
+                  <Select.Option key="windows" value="windows"> <Icon type="windows" /> </Select.Option>
+                  <Select.Option key="alipay" value="alipay"> <Icon type="alipay" /> </Select.Option>
+                </Select>
+              )}
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/components/tabs/tablabelform/index.scss b/src/menu/components/tabs/tablabelform/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/menu/components/tabs/tablabelform/index.scss
diff --git a/src/menu/components/tabs/tabsetting/index.jsx b/src/menu/components/tabs/tabsetting/index.jsx
new file mode 100644
index 0000000..c6e6f00
--- /dev/null
+++ b/src/menu/components/tabs/tabsetting/index.jsx
@@ -0,0 +1,80 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Modal } from 'antd'
+
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import SettingForm from './settingform'
+import './index.scss'
+
+class DataSource extends Component {
+  static propTpyes = {
+    config: PropTypes.any,
+    updateConfig: PropTypes.func
+  }
+
+  state = {
+    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    visible: false,
+    setting: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    this.setState({setting: fromJS(config.setting).toJS()})
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  editDataSource = () => {
+    this.setState({
+      visible: true
+    })
+  }
+
+  verifySubmit = () => {
+    const { config } = this.props
+
+    this.verifyRef.handleConfirm().then(res => {
+
+      this.setState({
+        setting: res,
+        visible: false
+      })
+      this.props.updateConfig({...config, setting: res})
+    })
+  }
+
+  render () {
+    const { visible, dict, setting } = this.state
+
+    return (
+      <div className="model-menu-tabs-setting">
+        <Icon type="setting" onClick={() => this.editDataSource()} />
+        <Modal
+          wrapClassName="model-datasource-verify-modal popview-modal"
+          title={'鏍囩椤甸厤缃�'}
+          visible={visible}
+          width={700}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <SettingForm
+            dict={dict}
+            setting={setting}
+            wrappedComponentRef={(inst) => this.verifyRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default DataSource
\ No newline at end of file
diff --git a/src/menu/components/tabs/tabsetting/index.scss b/src/menu/components/tabs/tabsetting/index.scss
new file mode 100644
index 0000000..2cb686e
--- /dev/null
+++ b/src/menu/components/tabs/tabsetting/index.scss
@@ -0,0 +1,94 @@
+.model-menu-tabs-setting {
+  position: absolute;
+  right: 7px;
+  top: 5px;
+  z-index: 1;
+
+  >.anticon-setting {
+    font-size: 18px;
+    padding: 10px;
+  }
+
+  .model-input-group-wrapper {
+    padding: 0 20px;
+    display: inline-block;
+    width: 100%;
+    text-align: start;
+    vertical-align: top;
+    margin-bottom: 15px;
+
+    .model-input-wrapper {
+      position: relative;
+      display: table;
+      width: 100%;
+      border-collapse: separate;
+      border-spacing: 0;
+
+      .model-input-value {
+        display: table-cell;
+        width: 100%;
+        border: 1px solid #d9d9d9;
+        border-radius: 4px 0px 0px 4px;
+        overflow: hidden;
+        text-overflow:ellipsis;
+        white-space: nowrap;
+        padding: 2px 10px;
+        color: #ffffff;
+      }
+
+      .model-input-group-addon {
+        display: table-cell;
+        width: 1px;
+        position: relative;
+        padding: 0 11px;
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: normal;
+        font-size: 14px;
+        line-height: 1;
+        text-align: center;
+        background-color: #fafafa;
+        border: 1px solid #d9d9d9;
+        border-radius: 0px 4px 4px 0px;
+        white-space: nowrap;
+      }
+
+      .model-input-insert {
+        display: table-cell;
+        width: 100%;
+        border: 1px dotted #d9d9d9;
+        border-radius: 4px;
+        text-align: center;
+        cursor: pointer;
+
+        .anticon-plus {
+          padding: 6px;
+          font-size: 16px;
+          color: rgb(38, 194, 129);
+        }
+      }
+    }
+    .anticon-setting {
+      margin-right: 5px;
+      padding: 6px;
+      cursor: pointer;
+    }
+    .anticon-setting:hover {
+      color: #1890ff;
+    }
+    .anticon-close {
+      padding: 6px;
+      cursor: pointer;
+    }
+    .anticon-close:hover {
+      color: #ff4d4f;
+    }
+  }
+}
+.model-datasource-verify-modal {
+  .ant-modal {
+    top: 50px;
+    .ant-modal-body {
+      max-height: calc(100vh - 190px);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/menu/components/tabs/tabsetting/settingform/index.jsx b/src/menu/components/tabs/tabsetting/settingform/index.jsx
new file mode 100644
index 0000000..b80e165
--- /dev/null
+++ b/src/menu/components/tabs/tabsetting/settingform/index.jsx
@@ -0,0 +1,127 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd'
+
+// import { formRule } from '@/utils/option.js'
+import './index.scss'
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,       // 瀛楀吀椤�
+    setting: PropTypes.object,    // 鏁版嵁婧愰厤缃�
+  }
+
+  state = {}
+
+  UNSAFE_componentWillMount () {
+
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+
+  render() {
+    const { setting } = this.props
+    const { getFieldDecorator } = this.props.form
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div className="model-datasource-setting-form-box">
+        <Form {...formItemLayout} className="model-setting-form">
+          <Row gutter={24}>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�">
+                  <Icon type="question-circle" />
+                  缁勪欢鍚嶇О
+                </Tooltip>
+              }>
+                {getFieldDecorator('name', {
+                  initialValue: setting.name,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒�24浠姐��">
+                  <Icon type="question-circle" />
+                  瀹藉害
+                </Tooltip>
+              }>
+                {getFieldDecorator('span', {
+                  initialValue: setting.span || 12,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '瀹藉害!'
+                    }
+                  ]
+                })(<InputNumber min={1} max={24} precision={0} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="鏍囩浣嶇疆">
+                {getFieldDecorator('position', {
+                  initialValue: setting.position || 'top'
+                })(
+                  <Select>
+                    <Select.Option key="top" value="top"> top </Select.Option>
+                    <Select.Option key="bottom" value="bottom"> bottom </Select.Option>
+                    <Select.Option key="left" value="left"> left </Select.Option>
+                    <Select.Option key="right" value="right"> right </Select.Option>
+                  </Select>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏍囩浣嶇疆涓簍op鏃舵湁鏁堬紝榛樿鍊间负line銆�">
+                  <Icon type="question-circle" />
+                  椤电鏍峰紡
+                </Tooltip>
+              }>
+                {getFieldDecorator('tabStyle', {
+                  initialValue: setting.tabStyle || 'line'
+                })(
+                  <Radio.Group>
+                    <Radio value="line">line</Radio>
+                    <Radio value="card">card</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/menu/components/tabs/tabsetting/settingform/index.scss b/src/menu/components/tabs/tabsetting/settingform/index.scss
new file mode 100644
index 0000000..d24bedd
--- /dev/null
+++ b/src/menu/components/tabs/tabsetting/settingform/index.scss
@@ -0,0 +1,24 @@
+.model-datasource-setting-form-box {
+  position: relative;
+
+  .model-setting-form {
+    .data-source {
+      .ant-form-item-label {
+        width: 11%;
+      }
+      .ant-form-item-control-wrapper {
+        width: 89%;
+      }
+      .CodeMirror {
+        height: 150px;
+      }
+    }
+    .anticon-question-circle {
+      color: #c49f47;
+      margin-right: 3px;
+    }
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+}
\ No newline at end of file
diff --git a/src/menu/menushell/card.jsx b/src/menu/menushell/card.jsx
index 85eb1bb..3e7e882 100644
--- a/src/menu/menushell/card.jsx
+++ b/src/menu/menushell/card.jsx
@@ -6,8 +6,9 @@
 import './index.scss'
 
 const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
+const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
 
-const Card = ({ id, config, card, moveCard, findCard, editId, editCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
+const Card = ({ id, config, card, moveCard, findCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
   const originalIndex = findCard(id).index
   const [{ isDragging }, drag] = useDrag({
     item: { type: 'menu', id, originalIndex },
@@ -39,7 +40,9 @@
 
   const getCardComponent = () => {
     if (card.type === 'bar' || card.type === 'line') {
-      return (<AntvBar config={config} card={card} triggerEdit={editCard} editId={editId} updateConfig={updateConfig} />)
+      return (<AntvBar config={config} card={card} updateConfig={updateConfig} />)
+    } else if (card.type === 'tabs') {
+      return (<AntvTabs config={config} tabs={card} updateConfig={updateConfig} />)
     }
   }
 
diff --git a/src/menu/menushell/index.jsx b/src/menu/menushell/index.jsx
index ec759ce..61edf52 100644
--- a/src/menu/menushell/index.jsx
+++ b/src/menu/menushell/index.jsx
@@ -8,7 +8,7 @@
 import Card from './card'
 import './index.scss'
 
-const Container = ({config, editId, handleList, editCard, deleteCard, doubleClickCard }) => {
+const Container = ({config, handleList, deleteCard, doubleClickCard }) => {
   let target = null
 
   const [cards, setCards] = useState(config.components)
@@ -60,7 +60,8 @@
         uuid: Utils.getuuid(),
         type: item.component,
         subtype: item.subtype,
-        isNew: true
+        floor: 1,   // 缁勪欢鐨勫眰绾�
+        isNew: true // 鏂版坊鍔犳爣蹇楋紝鐢ㄤ簬鍒濆鍖�
       }
       
       let targetId = cards.length > 0 ? cards[cards.length - 1].uuid : 0
@@ -88,9 +89,7 @@
           key={card.uuid}
           config={config}
           card={card}
-          editId={editId}
           moveCard={moveCard}
-          editCard={editCard}
           delCard={deleteCard}
           findCard={findCard}
           hasDrop={hasDrop}
diff --git a/src/menu/menushell/index.scss b/src/menu/menushell/index.scss
index 82097cc..1051e80 100644
--- a/src/menu/menushell/index.scss
+++ b/src/menu/menushell/index.scss
@@ -28,7 +28,7 @@
     .remove-component {
       opacity: 1;
     }
-    .model-datasource > .anticon-setting {
+    .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
       opacity: 1;
     }
   }
@@ -36,7 +36,7 @@
     padding-top: 150px;
   }
 
-  .model-datasource > .anticon-setting {
+  .model-datasource > .anticon-setting, .model-menu-tabs-setting > .anticon-setting {
     font-size: 16px;
     padding: 5px;
     position: absolute;
diff --git a/src/menu/modelsource/option.jsx b/src/menu/modelsource/option.jsx
index c796863..0a9d5be 100644
--- a/src/menu/modelsource/option.jsx
+++ b/src/menu/modelsource/option.jsx
@@ -4,11 +4,13 @@
 import bar1 from '@/assets/mobimg/bar1.png'
 import line from '@/assets/mobimg/line.png'
 import line1 from '@/assets/mobimg/line1.png'
+import tabs from '@/assets/mobimg/tabs.png'
 
 // const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
+  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs' },
   { type: 'menu', url: line, component: 'line', subtype: 'line' },
   { type: 'menu', url: line1, component: 'line', subtype: 'line1' },
   { type: 'menu', url: bar, component: 'bar', subtype: 'bar' },
diff --git a/src/menu/searchcomponent/index.scss b/src/menu/searchcomponent/index.scss
index 716cdd7..f136ad8 100644
--- a/src/menu/searchcomponent/index.scss
+++ b/src/menu/searchcomponent/index.scss
@@ -1,5 +1,5 @@
 .model-custom-search-list {
-  padding: 5px 0px 0px;
+  padding: 0px;
 
   .anticon-question-circle {
     color: #c49f47;
diff --git a/src/tabviews/custom/index.jsx b/src/tabviews/custom/index.jsx
index ea43555..0f4623d 100644
--- a/src/tabviews/custom/index.jsx
+++ b/src/tabviews/custom/index.jsx
@@ -67,7 +67,7 @@
         console.warn('Parse Failure')
         config = ''
       }
-      
+
       // HS涓嶄娇鐢ㄨ嚜瀹氫箟璁剧疆
       if (result.LongParamUser && this.props.menuType !== 'HS') {
         try { // 閰嶇疆淇℃伅瑙f瀽
@@ -86,7 +86,7 @@
         })
         return
       }
-      
+
       // 椤甸潰鏈惎鐢ㄦ椂锛屾樉绀烘湭鍚敤椤甸潰
       if (!config.enabled) {
         this.setState({
@@ -112,17 +112,17 @@
                 item.initval = param.data[item.field]
               }
             }
-    
+
             if (!item.blacklist || item.blacklist.length === 0) return item
-    
+
             let _black = item.blacklist.filter(v => {
               return this.props.permRoles.indexOf(v) !== -1
             })
-    
+
             if (_black.length > 0) {
               item.Hide = 'true'
             }
-    
+
             return item
           })
 
@@ -141,6 +141,8 @@
 
       let params = []
       config.components.forEach(component => {
+        if (!component.format) return // 娌℃湁鍔ㄦ�佹暟鎹�
+
         let _customScript = ''
         component.scripts && component.scripts.forEach(script => {
           if (script.status !== 'false') {

--
Gitblit v1.8.0