From e543372cc70a19ff2630c79d8421c2c593e54e5f Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期三, 02 六月 2021 17:15:21 +0800
Subject: [PATCH] 2021-06-02

---
 src/menu/components/share/normalheader/index.scss                              |    3 
 src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx                |   83 +++
 src/mob/components/menubar/normal-menubar/menucomponent/index.scss             |    0 
 src/menu/components/share/pastecomponent/index.jsx                             |    2 
 src/mob/components/menubar/normal-menubar/menucomponent/index.jsx              |  187 ++++++++
 src/views/pcdesign/index.jsx                                                   |   12 
 src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss |   25 +
 src/mob/components/menubar/normal-menubar/index.jsx                            |  263 +++++++++++
 src/mob/mobshell/index.jsx                                                     |    1 
 src/menu/components/share/sourcecomponent/index.jsx                            |   13 
 src/utils/utils-custom.js                                                      |    5 
 src/mob/modulesource/option.jsx                                                |    2 
 src/menu/pastecontroller/index.jsx                                             |   11 
 src/components/mkIcon/index.jsx                                                |   67 +++
 src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx    |  155 +++++++
 src/components/mkIcon/index.scss                                               |   33 +
 src/mob/components/menubar/normal-menubar/index.scss                           |   62 ++
 src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx  |  302 +++++++++++++
 src/tabviews/custom/components/share/normalheader/index.scss                   |    3 
 src/assets/mobimg/menubar.png                                                  |    0 
 src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss   |   11 
 src/views/mobdesign/index.jsx                                                  |   16 
 src/mob/components/menubar/normal-menubar/wrapsetting/index.scss               |    7 
 src/mob/mobshell/card.jsx                                                      |    3 
 24 files changed, 1,247 insertions(+), 19 deletions(-)

diff --git a/src/assets/mobimg/menubar.png b/src/assets/mobimg/menubar.png
new file mode 100644
index 0000000..2766d21
--- /dev/null
+++ b/src/assets/mobimg/menubar.png
Binary files differ
diff --git a/src/components/mkIcon/index.jsx b/src/components/mkIcon/index.jsx
new file mode 100644
index 0000000..ba860be
--- /dev/null
+++ b/src/components/mkIcon/index.jsx
@@ -0,0 +1,67 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Icon, Row, Col, Button } from 'antd'
+
+import { minkeIconSystem } from '@/utils/option.js'
+import './index.scss'
+
+class MkIcon extends Component {
+  static propTpyes = {
+    onChange: PropTypes.func
+  }
+
+  state = {
+    selectIcon: '',
+    icons: [...minkeIconSystem.normal, ...minkeIconSystem.trademark, ...minkeIconSystem.data, ...minkeIconSystem.edit, ...minkeIconSystem.hint, ...minkeIconSystem.direction],
+    visible: false
+  }
+
+  UNSAFE_componentWillMount () {
+    let val = ''
+    if (this.props['data-__meta']) {
+      val = this.props['data-__meta'].initialValue || ''
+    }
+    this.setState({selectIcon: val})
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  checkIcon = (val) => {
+    this.setState({selectIcon: val, visible: false})
+    this.props.onChange(val)
+  }
+
+  render() {
+    const { selectIcon, visible, icons } = this.state
+
+    return (
+      <div className="mk-icon-box">
+        {selectIcon ? <Icon type={selectIcon}/> : null}
+        <Icon onClick={() => this.setState({visible: true})} type="appstore"/>
+        <Modal
+          wrapClassName="popview-modal mk-icon-wrap"
+          title={'鍥炬爣閫夋嫨'}
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          onCancel={() => { this.setState({ visible: false }) }}
+          footer={[
+            <Button key="close" onClick={() => { this.setState({ visible: false }) }}>鍏抽棴</Button>
+          ]}
+          destroyOnClose
+        >
+          <Row>
+            {icons.map(icon => <Col className={icon === selectIcon ? 'active' : ''} key={icon} span={4}>
+              <Icon onClick={() => this.checkIcon(icon)} type={icon} />
+            </Col>)}
+          </Row>
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default MkIcon
\ No newline at end of file
diff --git a/src/components/mkIcon/index.scss b/src/components/mkIcon/index.scss
new file mode 100644
index 0000000..1d15d8a
--- /dev/null
+++ b/src/components/mkIcon/index.scss
@@ -0,0 +1,33 @@
+.mk-icon-box {
+  display: block;
+  height: 32px;
+  border: 1px solid #d9d9d9;
+  border-radius: 4px;
+  line-height: 32px;
+  padding: 0px 0px 0px 10px;
+
+  .anticon:last-child {
+    float: right;
+    line-height: 32px;
+    padding: 0 10px;
+    border-left: 1px solid #d9d9d9;
+  }
+}
+.mk-icon-box:hover {
+  border-color: #1890ff;
+}
+.mk-icon-wrap {
+  .ant-col {
+    text-align: center;
+    line-height: 55px;
+    .anticon {
+      font-size: 30px;
+      cursor: pointer;
+    }
+  }
+  .active.ant-col {
+    .anticon {
+      color: #1890ff;
+    }
+  }
+}
diff --git a/src/menu/components/share/normalheader/index.scss b/src/menu/components/share/normalheader/index.scss
index 6f01a79..ed805b2 100644
--- a/src/menu/components/share/normalheader/index.scss
+++ b/src/menu/components/share/normalheader/index.scss
@@ -3,13 +3,14 @@
   height: 45px;
   border-bottom: 1px solid #e8e8e8;
   overflow: hidden;
+  line-height: 45px;
 
   .title {
     text-decoration: inherit;
     font-weight: inherit;
     font-style: inherit;
     float: left;
-    line-height: 45px;
+    line-height: inherit;
     margin-left: 10px;
     position: relative;
     z-index: 1;
diff --git a/src/menu/components/share/pastecomponent/index.jsx b/src/menu/components/share/pastecomponent/index.jsx
index e9c8bf3..e4d8edf 100644
--- a/src/menu/components/share/pastecomponent/index.jsx
+++ b/src/menu/components/share/pastecomponent/index.jsx
@@ -186,6 +186,8 @@
         config.search.push(res)
       } else if (type === 'cardcell') {
         config.subcards.push(res)
+      } else if (type === 'menucell') {
+        config.subMenus.push(res)
       } else if (type === 'cols') {
         config.cols = config.cols.filter(col => !col.origin)
 
diff --git a/src/menu/components/share/sourcecomponent/index.jsx b/src/menu/components/share/sourcecomponent/index.jsx
index a5ed3e6..d59dfc1 100644
--- a/src/menu/components/share/sourcecomponent/index.jsx
+++ b/src/menu/components/share/sourcecomponent/index.jsx
@@ -14,12 +14,23 @@
   }
 
   state = {
-    url: this.props.value,
+    url: '',
     visible: ''
   }
 
   UNSAFE_componentWillMount () {
+    const { value } = this.props
+    let val = ''
 
+    if (value) {
+      val = value
+    } else if (this.props['data-__meta']) {
+      val = this.props['data-__meta'].initialValue || ''
+    }
+
+    this.setState({
+      url: val,
+    })
   }
 
   shouldComponentUpdate (nextProps, nextState) {
diff --git a/src/menu/pastecontroller/index.jsx b/src/menu/pastecontroller/index.jsx
index d80b944..8283c68 100644
--- a/src/menu/pastecontroller/index.jsx
+++ b/src/menu/pastecontroller/index.jsx
@@ -60,6 +60,11 @@
         cell = this.resetconfig(cell, item, true, copyBtns)
         return cell
       })
+    } else if (item.type === 'menubar') {
+      item.subMenus = item.subMenus.map(cell => {
+        cell.uuid = Utils.getuuid()
+        return cell
+      })
     } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
       item.subcards.forEach(card => {
         card.uuid = Utils.getuuid()
@@ -196,9 +201,13 @@
     const { Tab } = this.props
 
     let isgroup = Tab && Tab.type === 'group' ? true : false
+    let options = ['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter']
 
+    if (sessionStorage.getItem('appType') === 'mob') {
+      options.push('menubar')
+    }
     this.pasteFormRef.handleConfirm().then(res => {
-      if (!isgroup && !['tabs', 'datacard', 'propcard', 'mainsearch', 'group', 'normaltable', 'tablecard', 'line', 'bar', 'pie', 'dashboard', 'scatter'].includes(res.copyType)) {
+      if (!isgroup && !options.includes(res.copyType)) {
         notification.warning({
           top: 92,
           message: '閰嶇疆淇℃伅鏍煎紡閿欒锛�',
diff --git a/src/mob/components/menubar/normal-menubar/index.jsx b/src/mob/components/menubar/normal-menubar/index.jsx
new file mode 100644
index 0000000..e2e9dc2
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/index.jsx
@@ -0,0 +1,263 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Icon, Popover, Modal } from 'antd'
+
+import asyncComponent from '@/utils/asyncComponent'
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import { resetStyle } from '@/utils/utils-custom.js'
+import MKEmitter from '@/utils/events.js'
+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 WrapComponent = asyncIconComponent(() => import('./wrapsetting'))
+const MenuComponent = asyncComponent(() => import('./menucomponent'))
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
+const PasteComponent = asyncIconComponent(() => import('@/menu/components/share/pastecomponent'))
+const UserComponent = asyncIconComponent(() => import('@/menu/components/share/usercomponent'))
+const NormalHeader = asyncComponent(() => import('@/menu/components/share/normalheader'))
+
+const { confirm } = Modal
+
+class NoramlMenuBar extends Component {
+  static propTpyes = {
+    card: PropTypes.object,
+    deletecomponent: PropTypes.func,
+    updateConfig: PropTypes.func,
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    card: null,
+    back: false
+  }
+
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    if (card.isNew) {
+      let _card = {
+        uuid: card.uuid,
+        type: card.type,
+        floor: card.floor,
+        tabId: '',
+        parentId: '',
+        dataName: card.dataName || '',
+        width: card.width || 24,
+        name: card.name,
+        subtype: card.subtype,
+        wrap: { name: card.name, width: card.width || 24, title: '' },
+        style: { marginLeft: '0px', marginRight: '0px', marginTop: '8px', marginBottom: '8px' },
+        headerStyle: { fontSize: '16px', borderBottomWidth: '1px', borderBottomColor: '#e8e8e8' },
+        subMenus: [{
+          uuid: Utils.getuuid(),
+          setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '瀹㈡埛', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' },
+          style: {
+            paddingTop: '15px', paddingBottom: '15px'
+          }
+        }]
+      }
+
+      if (card.config) {
+        let config = fromJS(card.config).toJS()
+
+        _card.wrap = config.wrap
+        _card.wrap.name = card.name
+        _card.style = config.style
+        _card.headerStyle = config.headerStyle
+
+        _card.subMenus = config.subMenus.map(item => {
+          item.uuid = Utils.getuuid()
+          
+          return item
+        })
+      }
+      this.setState({
+        card: _card
+      })
+      this.props.updateConfig(_card)
+    } else {
+      this.setState({
+        card: fromJS(card).toJS()
+      })
+    }
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('submitStyle', this.getStyle)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    return !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('submitStyle', this.getStyle)
+  }
+
+  /**
+   * @description 鍗$墖琛屽灞備俊鎭洿鏂帮紙鏁版嵁婧愶紝鏍峰紡绛夛級
+   */
+  updateComponent = (component) => {
+    this.setState({
+      card: component
+    })
+
+    component.width = component.wrap.width
+    component.name = component.wrap.name
+
+    this.props.updateConfig(component)
+  }
+
+  /**
+   * @description 鍗曚釜鍗$墖淇℃伅鏇存柊
+   */
+  updateCard = (cell) => {
+    let card = fromJS(this.state.card).toJS()
+
+    card.subMenus = card.subMenus.map(item => {
+      if (item.uuid === cell.uuid) return cell
+      return item
+    })
+
+    this.setState({card})
+
+    this.props.updateConfig(card)
+  }
+
+  /**
+   * @description 鍗曚釜鍗$墖淇℃伅鏇存柊
+   */
+  deleteCard = (cell) => {
+    let card = fromJS(this.state.card).toJS()
+    let _this = this
+
+    confirm({
+      content: '纭畾鍒犻櫎鍗$墖鍚楋紵',
+      onOk() {
+        card.subMenus = card.subMenus.filter(item => item.uuid !== cell.uuid)
+
+        _this.setState({card})
+        _this.props.updateConfig(card)
+      },
+      onCancel() {}
+    })
+  }
+
+  changeStyle = () => {
+    const { card } = this.state
+
+    MKEmitter.emit('changeStyle', [card.uuid], ['background', 'border', 'padding', 'margin'], card.style)
+  }
+
+  getStyle = (comIds, style) => {
+    const { card } = this.state
+
+    if (comIds.length !== 1 || comIds[0] !== card.uuid) return
+
+    let _card = {...card, style}
+
+    this.setState({
+      card: _card
+    })
+    
+    this.props.updateConfig(_card)
+  }
+
+  addMenu = () => {
+    let card = fromJS(this.state.card).toJS()
+
+    let newcard = {
+      uuid: Utils.getuuid(),
+      setting: { type: 'menu', width: 6, sign: 'icon', icon: 'user', name: '瀹㈡埛', url: '', color: '#ffffff', iconFont: 20, padding: 12, background: '#1890ff', imgWidth: '' },
+      style: {
+        paddingTop: '15px', paddingBottom: '15px'
+      }
+    }
+
+    if (card.subMenus.length > 0) {
+      newcard = fromJS(card.subMenus.slice(-1)[0]).toJS()
+      newcard.uuid = Utils.getuuid()
+    }
+
+    card.subMenus.push(newcard)
+    
+    this.setState({card})
+    this.props.updateConfig(card)
+  }
+
+  move = (item, direction) => {
+    let card = fromJS(this.state.card).toJS()
+
+    let dragIndex = card.subMenus.findIndex(c => c.uuid === item.uuid)
+    let hoverIndex = null
+
+    if (direction === 'left') {
+      hoverIndex = dragIndex - 1
+    } else {
+      hoverIndex = dragIndex + 1
+    }
+
+    if (hoverIndex === -1 || hoverIndex === card.subMenus.length) return 
+
+    card.subMenus.splice(hoverIndex, 0, ...card.subMenus.splice(dragIndex, 1))
+
+    this.setState({card})
+    this.props.updateConfig(card)
+  }
+
+  clickComponent = (e) => {
+    if (sessionStorage.getItem('style-control') === 'true' || sessionStorage.getItem('style-control') === 'component') {
+      e.stopPropagation()
+      MKEmitter.emit('clickComponent', this.state.card)
+    }
+  }
+
+  render() {
+    const { card } = this.state
+
+    let offset = 0
+    if (card.wrap.cardFloat && card.wrap.cardFloat !== 'left') {
+      let _width = 0
+      card.subMenus.forEach(card => {
+        _width += card.setting.width
+      })
+      offset = _width < 24 ? 24 - _width : 0
+      if (card.wrap.cardFloat === 'center') {
+        offset = Math.floor(offset / 2)
+      }
+    }
+
+    let _style = resetStyle(card.style)
+
+    return (
+      <div className="menu-menubar-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}>
+        <NormalHeader config={card} updateComponent={this.updateComponent}/>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <Icon className="plus" title="娣诲姞鑿滃崟" onClick={this.addMenu} type="plus" />
+            <WrapComponent config={card} updateConfig={this.updateComponent} />
+            <CopyComponent type="normalmenu" card={card}/>
+            <PasteComponent config={card} options={['menucell']} updateConfig={this.updateComponent} />
+            <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
+            <UserComponent config={card}/>
+            <Icon className="close" title="鍒犻櫎缁勪欢" type="delete" onClick={() => this.props.deletecomponent(card.uuid)} />
+          </div>
+        } trigger="hover">
+          <Icon type="tool" />
+        </Popover>
+        {card.subMenus.map((menu, index) => (<MenuComponent key={menu.uuid} offset={!index ? offset : 0} cards={card} card={menu} move={this.move} updateElement={this.updateCard} deleteElement={this.deleteCard}/>))}
+      </div>
+    )
+  }
+}
+
+export default NoramlMenuBar
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/index.scss b/src/mob/components/menubar/normal-menubar/index.scss
new file mode 100644
index 0000000..c4c97f1
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/index.scss
@@ -0,0 +1,62 @@
+.menu-menubar-edit-box {
+  position: relative;
+  box-sizing: border-box;
+  background: #ffffff;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+  min-height: 20px;
+  
+  .card-control {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    .anticon-tool {
+      right: auto;
+      left: 1px;
+      padding: 1px;
+    }
+  }
+  .anticon-tool {
+    position: absolute;
+    z-index: 2;
+    font-size: 16px;
+    right: 1px;
+    top: 1px;
+    cursor: pointer;
+    padding: 5px;
+    background: rgba(255, 255, 255, 0.55);
+  }
+
+  .menu-item {
+    overflow: hidden;
+    position: relative;
+    min-height: 20px;
+    .menu-name {
+      text-align: center;
+      font-style: inherit;
+      font-weight: inherit;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    .menu-sign {
+      text-align: center;
+      .anticon {
+        border-radius: 50%;
+      }
+      img {
+        border-radius: 50%;
+      }
+    }
+  }
+}
+.menu-menubar-edit-box::after {
+  display: block;
+  content: ' ';
+  clear: both;
+}
+.menu-menubar-edit-box:hover {
+  z-index: 1;
+  box-shadow: 0px 0px 4px #1890ff;
+}
diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx b/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx
new file mode 100644
index 0000000..e900692
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/menucomponent/index.jsx
@@ -0,0 +1,187 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { is, fromJS } from 'immutable'
+import { Modal, Popover, Icon, Col } from 'antd'
+
+import asyncIconComponent from '@/utils/asyncIconComponent'
+import zhCN from '@/locales/zh-CN/model.js'
+import enUS from '@/locales/en-US/model.js'
+import SettingForm from './settingform'
+import { resetStyle } from '@/utils/utils-custom.js'
+import MKEmitter from '@/utils/events.js'
+import './index.scss'
+
+const CopyComponent = asyncIconComponent(() => import('@/menu/components/share/copycomponent'))
+
+class MenuBoxComponent extends Component {
+  static propTpyes = {
+    offset: PropTypes.any,           // 鍋忕Щ閲�
+    cards: PropTypes.object,         // 鍗$墖琛岄厤缃俊鎭�
+    card: PropTypes.object,          // 鍗$墖閰嶇疆淇℃伅
+    move: PropTypes.func,            // 鍗$墖绉诲姩
+    deleteElement: PropTypes.func,   // 鍗$墖鍒犻櫎
+    updateElement: PropTypes.func    // 鑿滃崟閰嶇疆鏇存柊
+  }
+
+  state = {
+    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    card: null,            // 鍗$墖淇℃伅锛屽寘鎷鍙嶉潰
+    formlist: null,        // 璁剧疆琛ㄥ崟淇℃伅
+    visible: false,        // 妯℃�佹鎺у埗
+  }
+
+  /**
+   * @description 鎼滅储鏉′欢鍒濆鍖�
+   */
+  UNSAFE_componentWillMount () {
+    const { card } = this.props
+
+    this.setState({
+      card: fromJS(card).toJS()
+    })
+  }
+
+  componentDidMount () {
+    MKEmitter.addListener('submitStyle', this.getStyle)
+  }
+
+  shouldComponentUpdate (nextProps, nextState) {
+    const { cards } = this.props
+    
+    return !is(fromJS(cards.wrap), fromJS(nextProps.cards.wrap)) || !is(fromJS(this.state), fromJS(nextState))
+  }
+
+  /**
+   * @description 缁勪欢閿�姣侊紝娓呴櫎state鏇存柊锛屾竻闄ゅ揩鎹烽敭璁剧疆
+   */
+  componentWillUnmount () {
+    this.setState = () => {
+      return
+    }
+    MKEmitter.removeListener('submitStyle', this.getStyle)
+  }
+
+  getStyle = (comIds, style) => {
+    const { cards } = this.props
+    const { card } = this.state
+
+    if (comIds.length !== 2 || comIds[0] !== cards.uuid || comIds[1] !== card.uuid) return
+
+    let _card = fromJS(card).toJS()
+    _card.style = style
+
+    this.setState({
+      card: _card
+    })
+
+    this.props.updateElement(_card)
+  }
+
+  changeStyle = () => {
+    const { cards } = this.props
+    const { card } = this.state
+
+    let _style = card.style ? fromJS(card.style).toJS() : {}
+    let options = ['font', 'border', 'padding']
+
+    MKEmitter.emit('changeStyle', [cards.uuid, card.uuid], options, _style)
+  }
+
+  settingSubmit = () => {
+    const { card } = this.state
+
+    this.settingRef.handleConfirm().then(res => {
+      this.setState({
+        visible: false,
+        card: {...card, setting: res}
+      })
+
+      this.props.updateElement({...card, setting: res})
+    })
+  }
+
+  changeMenu = () => {
+    const { card } = this.state
+
+    if (card.setting.type === 'link') {
+      window.open(card.setting.linkurl)
+    } else {
+      MKEmitter.emit('changeEditMenu', {
+        fixed: card.setting.type === 'menu',
+        MenuID: card.setting.type === 'linkmenu' ? card.setting.linkMenuId : card.uuid,
+        copyMenuId: card.setting.type === 'menu' ? card.setting.copyMenuId : '',
+        MenuNo: card.setting.MenuNo || '',
+        MenuName: card.setting.name,
+      })
+    }
+  }
+
+  render() {
+    const { cards, offset } = this.props
+    const { card, visible, dict } = this.state
+
+    let _style = {...card.style}
+
+    if (_style.shadow) {
+      _style.boxShadow = '0 0 4px ' + _style.shadow
+    }
+
+    _style = resetStyle(_style)
+
+    return (
+      <Col span={card.setting.width || 6} offset={offset || 0}>
+        <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+          <div className="mk-popover-control">
+            <Icon className="edit" title="缂栬緫" type="edit" onClick={() => this.setState({visible: true})} />
+            <CopyComponent type="menucell" card={card}/>
+            <Icon className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle} type="font-colors" />
+            <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
+              <div className="mk-popover-control">
+                <Icon className="plus" title="宸︾Щ" type="arrow-left" onClick={() => this.props.move(card, 'left')} />
+                <Icon className="close" title="鍙崇Щ" type="arrow-right" onClick={() => this.props.move(card, 'right')} />
+              </div>
+            } trigger="hover" getPopupContainer={() => document.getElementById(card.uuid + 'swap')}>
+              <Icon type="swap" id={card.uuid + 'swap'}/>
+            </Popover>
+            <Icon className="close" title="鍒犻櫎鑿滃崟" type="delete" onClick={() => this.props.deleteElement(card)} />
+          </div>
+        } trigger="hover">
+          <div className="menu-item" onDoubleClick={() => this.changeMenu()} style={_style}>
+            {card.setting.sign === 'icon' ? <div className="menu-sign">
+              <Icon style={{
+                fontSize: card.setting.iconFont || 20,
+                padding: card.setting.padding,
+                background: card.setting.background,
+                color: card.setting.color
+              }} type={card.setting.icon}/>
+            </div> : <div className="menu-sign">
+              <img style={{width: card.setting.imgWidth, height: card.setting.imgWidth}} src={card.setting.url} alt=""/>
+            </div>}
+            <div className="menu-name">{card.setting.name}</div>
+          </div>
+        </Popover>
+        <Modal
+          wrapClassName="popview-modal"
+          title={'鑿滃崟璁剧疆'}
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.settingSubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <SettingForm
+            dict={dict}
+            cards={cards}
+            setting={card.setting}
+            inputSubmit={this.settingSubmit}
+            wrappedComponentRef={(inst) => this.settingRef = inst}
+          />
+        </Modal>
+      </Col>
+    )
+  }
+}
+
+export default MenuBoxComponent
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/index.scss b/src/mob/components/menubar/normal-menubar/menucomponent/index.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/menucomponent/index.scss
diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx
new file mode 100644
index 0000000..2110030
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.jsx
@@ -0,0 +1,302 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Radio, Tooltip, Icon, Input, InputNumber, Select } from 'antd'
+
+import asyncComponent from '@/utils/asyncComponent'
+import './index.scss'
+
+const { TextArea } = Input
+const SourceComponent = asyncComponent(() => import('@/menu/components/share/sourcecomponent'))
+const ColorSketch = asyncComponent(() => import('@/mob/colorsketch'))
+const MkIcon = asyncComponent(() => import('@/components/mkIcon'))
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,      // 瀛楀吀椤�
+    cards: PropTypes.object,     // 鍗$墖闆�
+    setting: PropTypes.object,   // 鏁版嵁婧愰厤缃�
+    inputSubmit: PropTypes.func  // 鍥炶溅浜嬩欢
+  }
+
+  state = {
+    type: this.props.setting.type,
+    sign: this.props.setting.sign,
+    menulist: []
+  }
+
+  UNSAFE_componentWillMount() {
+    let menulist = sessionStorage.getItem('appMenus')
+
+    if (menulist) {
+      try {
+        menulist = JSON.parse(menulist)
+      } catch {
+        menulist = []
+      }
+    } else {
+      menulist = []
+    }
+    this.setState({menulist})
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  render() {
+    const { setting } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { menulist, type, sign } = this.state
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div className="model-menubar-menu-card-setting-form">
+        <Form {...formItemLayout}>
+          <Row gutter={24}>
+            <Col span={12}>
+              <Form.Item label="鑿滃崟鍚嶇О">
+                {getFieldDecorator('name', {
+                  initialValue: setting.name || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '鑿滃崟鍚嶇О!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="鑿滃崟鍙傛暟">
+                {getFieldDecorator('MenuNo', {
+                  initialValue: setting.MenuNo || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '鑿滃崟鍙傛暟!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��">
+                  <Icon type="question-circle" />
+                  鍗$墖瀹藉害
+                </Tooltip>
+              }>
+                {getFieldDecorator('width', {
+                  initialValue: setting.width || 24,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '瀹藉害!'
+                    }
+                  ]
+                })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit}/>)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="绫诲瀷">
+                {getFieldDecorator('type', {
+                  initialValue: type,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.select'] + '绫诲瀷!'
+                    }
+                  ]
+                })(
+                  <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({type: e.target.value})}>
+                    <Radio value="menu">鑿滃崟</Radio>
+                    <Radio value="link">閾炬帴</Radio>
+                    <Radio value="linkmenu">鍏宠仈鑿滃崟</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {type === 'menu' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="澶嶅埗鑿滃崟浠呭湪褰撳墠鑿滃崟涓嶅瓨鍦ㄦ椂鏈夋晥銆�">
+                  <Icon type="question-circle" style={{color: '#c49f47', marginRight: '3px'}}/>
+                  澶嶅埗鑿滃崟
+                </Tooltip>
+              }>
+                {getFieldDecorator('copyMenuId', {
+                  initialValue: setting.copyMenuId || ''
+                })(
+                  <Select allowClear>
+                    {menulist.map(item => (<Select.Option key={item.MenuID} value={item.MenuID}>{item.MenuName}</Select.Option>))}
+                  </Select>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {type === 'linkmenu' ? <Col span={12}>
+              <Form.Item label="鍏宠仈鑿滃崟">
+                {getFieldDecorator('linkMenuId', {
+                  initialValue: setting.linkMenuId || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.select'] + '鍏宠仈鑿滃崟!'
+                    }
+                  ]
+                })(
+                  <Select
+                    showSearch
+                    filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  >
+                    {menulist.map(option =>
+                      <Select.Option key={option.MenuID} value={option.MenuID}>{option.MenuName}</Select.Option>
+                    )}
+                  </Select>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {type === 'link' ? <Col span={24} className="textarea">
+              <Form.Item label="閾炬帴">
+                {getFieldDecorator('linkurl', {
+                  initialValue: setting.linkurl || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '閾炬帴!'
+                    }
+                  ]
+                })( <TextArea rows={2}/> )}
+              </Form.Item>
+            </Col> : null}
+            <Col span={12}>
+              <Form.Item label="鏍囧織">
+                {getFieldDecorator('sign', {
+                  initialValue: sign,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.select'] + '鏍囧織!'
+                    }
+                  ]
+                })(
+                  <Radio.Group style={{whiteSpace: 'nowrap'}} onChange={(e) => this.setState({sign: e.target.value})}>
+                    <Radio value="icon">鍥炬爣</Radio>
+                    <Radio value="image">鍥剧墖</Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            {sign === 'icon' ? <Col span={12}>
+              <Form.Item label="鍥炬爣">
+                {getFieldDecorator('icon', {
+                  initialValue: setting.icon || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.select'] + '鍥炬爣!'
+                    }
+                  ]
+                })(
+                  <MkIcon />
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'icon' ? <Col span={12}>
+              <Form.Item label="瀛椾綋澶у皬">
+                {getFieldDecorator('iconFont', {
+                  initialValue: setting.iconFont || 20
+                })(
+                  <InputNumber min={12} max={200} precision={0} onPressEnter={this.handleSubmit}/>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'icon' ? <Col span={12}>
+              <Form.Item label="鍐呰竟璺�">
+                {getFieldDecorator('padding', {
+                  initialValue: setting.padding || 12
+                })(
+                  <InputNumber min={0} max={200} precision={0} onPressEnter={this.handleSubmit}/>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'icon' ? <Col span={12}>
+              <Form.Item label="瀛椾綋棰滆壊">
+                {getFieldDecorator('color', {
+                  initialValue: setting.color || '#ffffff'
+                })(
+                  <ColorSketch />
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'icon' ? <Col span={12}>
+              <Form.Item label="鑳屾櫙鑹�">
+                {getFieldDecorator('background', {
+                  initialValue: setting.background || '#1890ff'
+                })(
+                  <ColorSketch />
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'image' ? <Col span={12}>
+              <Form.Item label="鍥剧墖鍦板潃">
+                {getFieldDecorator('url', {
+                  initialValue: setting.url || '',
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '鍥剧墖鍦板潃!'
+                    }
+                  ]
+                })(
+                  <SourceComponent type="" placement="right"/>
+                )}
+              </Form.Item>
+            </Col> : null}
+            {sign === 'image' ? <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鍥剧墖瀹藉害涓庨珮搴︾浉褰擄紝浣跨敤鐨勫浘鐗囨瘮渚嬪簲涓�1:1銆�">
+                  <Icon type="question-circle" />
+                  鍥剧墖瀹藉害
+                </Tooltip>
+              }>
+                {getFieldDecorator('imgWidth', {
+                  initialValue: setting.imgWidth || 36
+                })(
+                  <InputNumber min={10} max={500} precision={0} onPressEnter={this.handleSubmit}/>
+                )}
+              </Form.Item>
+            </Col> : null}
+          </Row>
+        </Form>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss
new file mode 100644
index 0000000..91dfcf6
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/menucomponent/settingform/index.scss
@@ -0,0 +1,25 @@
+.model-menubar-menu-card-setting-form {
+  position: relative;
+
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+  .textarea {
+    .ant-form-item-label {
+      width: 16%;
+    }
+    .ant-form-item-control-wrapper {
+      width: 84%;
+    }
+  }
+  .ant-radio-wrapper {
+    margin-right: 3px;
+  }
+  .color-sketch-block {
+    margin-top: 7px;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx b/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx
new file mode 100644
index 0000000..81346a6
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/wrapsetting/index.jsx
@@ -0,0 +1,83 @@
+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: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
+    visible: false,
+    wrap: null
+  }
+
+  UNSAFE_componentWillMount () {
+    const { config } = this.props
+
+    this.setState({wrap: fromJS(config.wrap).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({
+        wrap: res,
+        visible: false
+      })
+      this.props.updateConfig({...config, wrap: res})
+    })
+  }
+
+  render () {
+    const { config } = this.props
+    const { visible, dict, wrap } = this.state
+
+    return (
+      <div className="model-menu-setting-wrap">
+        <Icon type="edit" title="缂栬緫" onClick={() => this.editDataSource()} />
+        <Modal
+          wrapClassName="popview-modal"
+          title={config.type === 'table' ? '琛ㄦ牸璁剧疆' : '鍗$墖璁剧疆'}
+          visible={visible}
+          width={800}
+          maskClosable={false}
+          okText={dict['model.submit']}
+          onOk={this.verifySubmit}
+          onCancel={() => { this.setState({ visible: false }) }}
+          destroyOnClose
+        >
+          <SettingForm
+            dict={dict}
+            wrap={wrap}
+            config={config}
+            inputSubmit={this.verifySubmit}
+            wrappedComponentRef={(inst) => this.verifyRef = inst}
+          />
+        </Modal>
+      </div>
+    )
+  }
+}
+
+export default DataSource
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss b/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss
new file mode 100644
index 0000000..04372e6
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/wrapsetting/index.scss
@@ -0,0 +1,7 @@
+.model-menu-setting-wrap {
+  display: inline-block;
+
+  >.anticon-edit {
+    color: #1890ff;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx
new file mode 100644
index 0000000..e501fa1
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.jsx
@@ -0,0 +1,155 @@
+import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+import { Form, Row, Col, Input, Radio, Tooltip, Icon, InputNumber, Select } from 'antd'
+
+import './index.scss'
+
+class SettingForm extends Component {
+  static propTpyes = {
+    dict: PropTypes.object,      // 瀛楀吀椤�
+    config: PropTypes.object,    // 鍗$墖琛屼俊鎭�
+    wrap: PropTypes.object,      // 鏁版嵁婧愰厤缃�
+    inputSubmit: PropTypes.func  // 鍥炶溅浜嬩欢
+  }
+
+  state = {
+    roleList: [],
+  }
+
+  UNSAFE_componentWillMount () {
+    let roleList = sessionStorage.getItem('sysRoles')
+    if (roleList) {
+      try {
+        roleList = JSON.parse(roleList)
+      } catch {
+        roleList = []
+      }
+    } else {
+      roleList = []
+    }
+
+    this.setState({roleList})
+  }
+
+  handleConfirm = () => {
+    // 琛ㄥ崟鎻愪氦鏃舵鏌ヨ緭鍏ュ�兼槸鍚︽纭�
+    return new Promise((resolve, reject) => {
+      this.props.form.validateFieldsAndScroll((err, values) => {
+        if (!err) {
+          resolve(values)
+        } else {
+          reject(err)
+        }
+      })
+    })
+  }
+
+  handleSubmit = (e) => {
+    e.preventDefault()
+
+    if (this.props.inputSubmit) {
+      this.props.inputSubmit()
+    }
+  }
+
+  render() {
+    const { wrap } = this.props
+    const { getFieldDecorator } = this.props.form
+    const { roleList } = this.state
+
+    const formItemLayout = {
+      labelCol: {
+        xs: { span: 24 },
+        sm: { span: 8 }
+      },
+      wrapperCol: {
+        xs: { span: 24 },
+        sm: { span: 16 }
+      }
+    }
+
+    return (
+      <div className="model-menubar-menu-setting-form">
+        <Form {...formItemLayout}>
+          <Row gutter={24}>
+            <Col span={12}>
+              <Form.Item label="鏍囬">
+                {getFieldDecorator('title', {
+                  initialValue: wrap.title || ''
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鐢ㄤ簬缁勪欢闂寸殑鍖哄垎銆�">
+                  <Icon type="question-circle" />
+                  缁勪欢鍚嶇О
+                </Tooltip>
+              }>
+                {getFieldDecorator('name', {
+                  initialValue: wrap.name,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '缁勪欢鍚嶇О!'
+                    }
+                  ]
+                })(<Input placeholder={''} autoComplete="off" onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label={
+                <Tooltip placement="topLeft" title="鏍呮牸甯冨眬锛屾瘡琛岀瓑鍒嗕负24鍒椼��">
+                  <Icon type="question-circle" />
+                  瀹藉害
+                </Tooltip>
+              }>
+                {getFieldDecorator('width', {
+                  initialValue: wrap.width || 24,
+                  rules: [
+                    {
+                      required: true,
+                      message: this.props.dict['form.required.input'] + '瀹藉害!'
+                    }
+                  ]
+                })(<InputNumber min={1} max={24} precision={0} onPressEnter={this.handleSubmit} />)}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="瀵归綈鏂瑰紡">
+                {getFieldDecorator('float', {
+                  initialValue: wrap.float || 'left'
+                })(
+                  <Radio.Group style={{whiteSpace: 'nowrap'}}>
+                    <Radio key="left" value="left"> 宸﹀榻� </Radio>
+                    <Radio key="center" value="center"> 灞呬腑 </Radio>
+                    <Radio key="right" value="right"> 鍙冲榻� </Radio>
+                  </Radio.Group>
+                )}
+              </Form.Item>
+            </Col>
+            <Col span={12}>
+              <Form.Item label="榛戝悕鍗�">
+                {getFieldDecorator('blacklist', {
+                  initialValue: wrap.blacklist || []
+                })(
+                  <Select
+                    showSearch
+                    mode="multiple"
+                    filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+                  >
+                    {roleList.map(option =>
+                      <Select.Option key={option.uuid} value={option.value}>{option.text}</Select.Option>
+                    )}
+                  </Select>
+                )}
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+    )
+  }
+}
+
+export default Form.create()(SettingForm)
\ No newline at end of file
diff --git a/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss
new file mode 100644
index 0000000..92283b8
--- /dev/null
+++ b/src/mob/components/menubar/normal-menubar/wrapsetting/settingform/index.scss
@@ -0,0 +1,11 @@
+.model-menubar-menu-setting-form {
+  position: relative;
+
+  .anticon-question-circle {
+    color: #c49f47;
+    margin-right: 3px;
+  }
+  .ant-input-number {
+    width: 100%;
+  }
+}
\ No newline at end of file
diff --git a/src/mob/mobshell/card.jsx b/src/mob/mobshell/card.jsx
index d5c2b39..897383f 100644
--- a/src/mob/mobshell/card.jsx
+++ b/src/mob/mobshell/card.jsx
@@ -23,6 +23,7 @@
 const NormalLogin = asyncComponent(() => import('@/pc/components/login/normal-login'))
 const NormalNavbar = asyncComponent(() => import('@/mob/components/navbar/normal-navbar'))
 const NormalTopbar = asyncComponent(() => import('@/mob/components/topbar/normal-navbar'))
+const NormalMenuBar = asyncComponent(() => import('@/mob/components/menubar/normal-menubar'))
 
 const Card = ({ id, card, moveCard, findCard, delCard, updateConfig }) => {
   const originalIndex = findCard(id).index
@@ -113,6 +114,8 @@
       return (<NormalNavbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     } else if (card.type === 'topbar') {
       return (<NormalTopbar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
+    } else if (card.type === 'menubar') {
+      return (<NormalMenuBar card={card} updateConfig={updateConfig} deletecomponent={delCard}/>)
     }
   }
 
diff --git a/src/mob/mobshell/index.jsx b/src/mob/mobshell/index.jsx
index 3b3b89a..0552568 100644
--- a/src/mob/mobshell/index.jsx
+++ b/src/mob/mobshell/index.jsx
@@ -118,6 +118,7 @@
         form: '琛ㄥ崟',
         card: '鍗$墖',
         navbar: '瀵艰埅鏍�',
+        menubar: '鑿滃崟鏍�',
         login: '鐧诲綍'
       }
       let i = 1
diff --git a/src/mob/modulesource/option.jsx b/src/mob/modulesource/option.jsx
index bd0786f..1a016c5 100644
--- a/src/mob/modulesource/option.jsx
+++ b/src/mob/modulesource/option.jsx
@@ -22,11 +22,13 @@
 import dashboard from '@/assets/mobimg/dashboard.png'
 import NavTop from '@/assets/mobimg/navtop-mob.png'
 import scatter from '@/assets/mobimg/scatter.png'
+import MenuBar from '@/assets/mobimg/menubar.png'
 
 // 缁勪欢閰嶇疆淇℃伅
 export const menuOptions = [
   { type: 'menu', url: NavTop, component: 'topbar', subtype: 'topbar', title: '瀵艰埅鏍�' },
   { type: 'menu', url: Navbar, component: 'navbar', subtype: 'tabbar', title: '鑿滃崟鏍�' },
+  { type: 'menu', url: MenuBar, component: 'menubar', subtype: 'menubar', title: '鑿滃崟' },
   { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs', title: '鏍囩椤�', width: 24 },
   { type: 'menu', url: Mainsearch, component: 'search', subtype: 'mainsearch', title: '鎼滅储鏉′欢', width: 24 },
   { type: 'menu', url: card1, component: 'card', subtype: 'datacard', title: '鏁版嵁鍗�', width: 24 },
diff --git a/src/tabviews/custom/components/share/normalheader/index.scss b/src/tabviews/custom/components/share/normalheader/index.scss
index 3321603..3939c9a 100644
--- a/src/tabviews/custom/components/share/normalheader/index.scss
+++ b/src/tabviews/custom/components/share/normalheader/index.scss
@@ -5,13 +5,14 @@
   border-bottom: 1px solid #e8e8e8;
   overflow: hidden;
   letter-spacing: 0px;
+  line-height: 45px;
 
   .title {
     text-decoration: inherit;
     font-weight: inherit;
     font-style: inherit;
     float: left;
-    line-height: 45px;
+    line-height: inherit;
     margin-left: 10px;
     position: relative;
     z-index: 1;
diff --git a/src/utils/utils-custom.js b/src/utils/utils-custom.js
index a963563..cf2d151 100644
--- a/src/utils/utils-custom.js
+++ b/src/utils/utils-custom.js
@@ -280,6 +280,11 @@
           return cell
         })
         item.components = this.resetConfig(item.components)
+      } else if (item.type === 'menubar') {
+        item.subMenus = item.subMenus.map(cell => {
+          cell.uuid = this.getuuid()
+          return cell
+        })
       } else if (item.type === 'card' || item.type === 'carousel' || (item.type === 'table' && item.subtype === 'tablecard')) {
         item.subcards.forEach(card => {
           card.uuid = this.getuuid()
diff --git a/src/views/mobdesign/index.jsx b/src/views/mobdesign/index.jsx
index c11a768..b80811c 100644
--- a/src/views/mobdesign/index.jsx
+++ b/src/views/mobdesign/index.jsx
@@ -58,7 +58,7 @@
     delButtons: [],
     copyButtons: [],
     thawButtons: [],
-    activeKey: 'basedata',
+    activeKey: 'component',
     menuloading: false,
     oriConfig: null,
     config: null,
@@ -194,9 +194,9 @@
 
     if (menu.fixed && menu.MenuNo && menu.MenuName) {
       param.fixed = true
-      param.MenuNo = menu.MenuNo
-      param.MenuName = menu.MenuName
     }
+    param.MenuNo = menu.MenuNo || ''
+    param.MenuName = menu.MenuName || ''
 
     param = window.btoa(window.encodeURIComponent(JSON.stringify(param)))
 
@@ -443,8 +443,8 @@
             MenuID: MenuId,
             Template: 'webPage',
             enabled: false,
-            MenuName: '',
-            MenuNo: '',
+            MenuName: urlParam.MenuName || '',
+            MenuNo: urlParam.MenuNo || '',
             tables: [],
             components: [],
             viewType: 'menu',
@@ -459,10 +459,8 @@
         config.open_edition = result.open_edition || ''
         window.GLOB.urlFields = config.urlFields || []
 
-        if (urlParam.fixed) {
+        if (urlParam.fixed && urlParam.MenuName && urlParam.MenuNo) {
           config.fixed = true
-          config.MenuName = urlParam.MenuName
-          config.MenuNo = urlParam.MenuNo
         }
 
         let indeComs = []
@@ -476,6 +474,7 @@
           this.setState({
             oriConfig: isCreate ? null : config,
             config: fromJS(config).toJS(),
+            activeKey: isCreate ? 'basedata' : 'component',
             loading: false
           })
           window.GLOB.customMenu = config
@@ -665,6 +664,7 @@
 
       this.setState({
         oriConfig: isCreate ? null : fromJS(config).toJS(),
+        activeKey: isCreate ? 'basedata' : 'component',
         config: config,
         loading: false
       })
diff --git a/src/views/pcdesign/index.jsx b/src/views/pcdesign/index.jsx
index a03874f..183c884 100644
--- a/src/views/pcdesign/index.jsx
+++ b/src/views/pcdesign/index.jsx
@@ -167,9 +167,9 @@
 
     if (menu.fixed && menu.MenuNo && menu.MenuName) {
       param.fixed = true
-      param.MenuNo = menu.MenuNo
-      param.MenuName = menu.MenuName
     }
+    param.MenuNo = menu.MenuNo || ''
+    param.MenuName = menu.MenuName || ''
 
     param = window.btoa(window.encodeURIComponent(JSON.stringify(param)))
 
@@ -485,8 +485,8 @@
             MenuID: MenuId,
             Template: 'webPage',
             enabled: false,
-            MenuName: '',
-            MenuNo: '',
+            MenuName: urlParam.MenuName || '',
+            MenuNo: urlParam.MenuNo || '',
             tables: [],
             components: [],
             viewType: 'menu',
@@ -501,10 +501,8 @@
         config.open_edition = result.open_edition || ''
         window.GLOB.urlFields = config.urlFields || []
 
-        if (urlParam.fixed) {
+        if (urlParam.fixed && urlParam.MenuNo && urlParam.MenuName) {
           config.fixed = true
-          config.MenuName = urlParam.MenuName
-          config.MenuNo = urlParam.MenuNo
         }
 
         let indeComs = []

--
Gitblit v1.8.0