king
2020-09-23 0de207ebed200dffca41b8c974d1394cf328b03e
2020-09-23
18个文件已修改
5个文件已添加
516 ■■■■ 已修改文件
src/assets/css/main.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/mobimg/card1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/bgcontroller/index.jsx 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/bgcontroller/index.scss 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/data-card/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/chart/antv-bar/index.scss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/antv-tabs/index.scss 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/card.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/tabs/tabcomponents/index.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/datasource/index.jsx 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/card.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.jsx 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/menushell/index.scss 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/modelsource/option.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/chart/antv-bar-line/index.scss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/tabs/antv-tabs/index.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/index.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.jsx 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/menudesign/index.scss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/css/main.scss
@@ -286,6 +286,7 @@
      bottom: -3.8px!important;
    }
    .mk-popover-control {
      white-space: nowrap;
      i {
        padding: 5px 8px;
        cursor: pointer;
@@ -293,6 +294,9 @@
      }
      .edit {
        color: #1890ff;
      }
      .plus {
        color: #26C281;
      }
      .copy {
        color: #26C281;
@@ -303,6 +307,10 @@
      .profile {
        color: purple;
      }
      .model-menu-tabs-setting {
        display: inline-block;
        position: unset;
      }
    }
    .mk-popover-control::after {
      position: absolute;
src/assets/mobimg/card1.png
src/menu/bgcontroller/index.jsx
New file
@@ -0,0 +1,145 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { Form, Input } from 'antd'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import ColorSketch from '@/mob/colorsketch'
import FileUpload from '@/tabviews/zshare/fileupload'
import './index.scss'
class MobController extends Component {
  static propTpyes = {
    config: PropTypes.any,
    updateConfig: PropTypes.func,
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    backgroundColor: '',
    backgroundImage: '',
    bgimages: [],
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    let bgImg = config.style.backgroundImage || ''
    if (bgImg && /^linear-gradient/.test(bgImg)) {
      bgImg = bgImg.replace('linear-gradient(', '')
      bgImg = bgImg.replace(')', '')
    } else if (bgImg && /^url/.test(bgImg)) {
      bgImg = bgImg.replace('url(', '')
      bgImg = bgImg.replace(')', '')
    }
    this.setState({
      backgroundColor: config.style.backgroundColor,
      backgroundImage: bgImg
    })
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 修改背景颜色 ,颜色控件
   */
  changeBackgroundColor = (val) => {
    let config = fromJS(this.props.config).toJS()
    this.setState({
      backgroundColor: val
    })
    config.style.backgroundColor = val
    this.props.updateConfig(config)
  }
  /**
   * @description 修改字体颜色 ,手动输入
   */
  changeBackgroundColorInput = (e) => {
    let val = e.target.value
    this.setState({
      backgroundColor: val
    })
    let config = fromJS(this.props.config).toJS()
    config.style.backgroundColor = val
    this.props.updateConfig(config)
    // if (/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$|^[rR][gG][Bb][Aa]?[(]([\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),){2}[\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?[\s]*(0\.\d{1,2}|1|0)?[)]{1}$/.test(val)) {}
  }
  /**
   * @description 手动修改路径
   */
  changeImage = (e) => {
    let val = e.target.value
    this.setState({
      backgroundImage: val
    })
    let config = fromJS(this.props.config).toJS()
    val = val.replace(/^\s*|\s*$/ig, '')
    if (/^http|^\/\//.test(val)) {
      val = `url(${val})`
    } else if (/^#|,/ig.test(val)) {
      val = `linear-gradient(${val})`
    }
    config.style.backgroundImage = val
    this.props.updateConfig(config)
  }
  imgChange = (list) => {
    if (list[0] && list[0].response) {
      this.setState({
        bgimages: [],
        backgroundImage: list[0].response
      })
      let config = fromJS(this.props.config).toJS()
      config.style.backgroundImage = `url(${list[0].response})`
      this.props.updateConfig(config)
    } else {
      this.setState({bgimages: list})
    }
  }
  render () {
    const { backgroundColor, backgroundImage, bgimages } = this.state
    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 4 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 20 }
      }
    }
    return (
      <div className="menu-background-controller">
        <Form {...formItemLayout}>
          <Form.Item className="color-control" colon={false} label="颜色">
            <ColorSketch color={backgroundColor} changeColor={this.changeBackgroundColor} />
            <Input value={backgroundColor} onChange={this.changeBackgroundColorInput} />
          </Form.Item>
          <Form.Item colon={false} label="图片">
            <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
            <Input placeholder="" value={backgroundImage} autoComplete="off" onChange={this.changeImage}/>
          </Form.Item>
        </Form>
      </div>
    )
  }
}
export default MobController
src/menu/bgcontroller/index.scss
New file
@@ -0,0 +1,37 @@
.menu-background-controller {
  width: 100%;
  height: 100%;
  overflow: hidden;
  .color-control .ant-form-item-control {
    padding-top: 10px;
    line-height: 35px;
  }
}
.margin-popover {
  padding-top: 0px;
  .ant-popover-inner-content {
    width: 90px;
    padding: 0px 5px;
    .ant-menu-root.ant-menu-vertical {
      border: 0;
      .ant-menu-item {
        height: 30px;
        cursor: pointer;
        line-height: 30px;
      }
      .ant-menu-item:not(:last-child) {
        margin-bottom: 0px;
      }
      .ant-menu-item:first-child {
        margin-top: 10px;
      }
      .ant-menu-item:last-child {
        margin-bottom: 10px;
      }
    }
  }
  .ant-popover-arrow {
    display: none;
  }
}
src/menu/components/card/data-card/index.jsx
New file
@@ -0,0 +1,129 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
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('@/menu/datasource'))
const ActionComponent = asyncComponent(() => import('@/menu/actioncomponent'))
class antvBarLineChart extends Component {
  static propTpyes = {
    card: PropTypes.object,
    updateConfig: PropTypes.func,
  }
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    card: null
  }
  UNSAFE_componentWillMount () {
    const { card, menu } = this.props
    if (card.isNew) {
      let dataName = ''
      if (card.floor === 1) {
        while (!dataName) {
          let _dataName = Utils.getdataName()
          if (menu.components.filter(com => com.dataName === _dataName).length === 0) {
            dataName = _dataName
          }
        }
      }
      let _card = {
        uuid: card.uuid,
        type: card.type,
        floor: card.floor,
        tabId: card.tabId || '',
        parentId: card.parentId || '',
        format: 'array',   // 组件属性 - 数据格式
        pageable: false,   // 组件属性 - 是否可分页
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: dataName,
        subtype: card.subtype,
        setting: {span: 24, height: 200, interType: 'system', name: card.name},
        columns: [],
        scripts: [],
        search: [],
        action: [],
      }
      this.setState({
        card: _card
      })
      this.props.updateConfig(_card)
    } else {
      this.setState({
        card: fromJS(card).toJS()
      })
    }
  }
  componentDidMount () {
  }
  shouldComponentUpdate (nextProps, nextState) {
    return !is(fromJS(this.state), fromJS(nextState))
  }
  /**
   * @description 组件销毁,清除state更新,清除快捷键设置
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  updateComponent = (component) => {
    this.setState({
      card: component
    })
    this.props.updateConfig(component)
  }
  render() {
    const { card } = this.state
    return (
      <div className="menu-data-card-edit-box" style={{height: card.setting.height || 400}}>
        <SettingComponent
          config={card}
          updateConfig={this.updateComponent}
        />
        <div className="chart-header">
          <span className="chart-title">{card.setting.title || ''}</span>
        </div>
        <ActionComponent
          type="chart"
          config={card}
          tabs={[]}
          // setSubConfig={(_btn) => this.setSubConfig(_btn, 'button')}
          updateaction={this.updateComponent}
        />
        <div className="canvas" id={card.uuid}></div>
      </div>
    )
  }
}
const mapStateToProps = (state) => {
  return {
    menu: state.customMenu
  }
}
const mapDispatchToProps = () => {
  return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(antvBarLineChart)
src/menu/components/card/data-card/index.scss
New file
@@ -0,0 +1,9 @@
.menu-data-card-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
}
.menu-data-card-edit-box:hover {
  box-shadow: 0px 0px 2px #e8e8e8;
}
src/menu/components/chart/antv-bar/index.jsx
@@ -75,7 +75,7 @@
        switchable: false, // 组件属性 - 数据是否可切换
        dataName: dataName,
        subtype: card.subtype,
        setting: {span: card.floor === 1 ? 12 : 24, height: 400, interType: 'system', name: card.name},
        setting: {span: 24, height: 400, interType: 'system', name: card.name},
        columns: [],
        scripts: [],
        search: [],
@@ -456,6 +456,31 @@
      })
  
      chart.data(dv.rows)
      // chart.axis(X_axis, {
      //   label: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   },
      //   line: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   }
      // })
      // chart.axis('value', {
      //   grid: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   },
      //   label: {
      //     style: {
      //       fill: '#ffffff',
      //     }
      //   }
      // })
  
      chart.scale('value', {
        nice: true
@@ -465,7 +490,12 @@
        chart.legend(false)
      } else {
        chart.legend({
          position: plot.legend
          position: plot.legend,
          // itemName: {
          //   style: {
          //     fill: '#ffffff',
          //   }
          // }
        })
      }
  
src/menu/components/chart/antv-bar/index.scss
@@ -1,7 +1,7 @@
.menu-line-chart-edit-box {
  position: relative;
  // margin-bottom: 0px;
  box-sizing: border-box;
  background: #ffffff;
  
  .canvas {
    margin: 0px;
src/menu/components/tabs/antv-tabs/index.jsx
@@ -21,6 +21,7 @@
class antvBarLineChart extends Component {
  static propTpyes = {
    tabs: PropTypes.object,
    deleteTabs: PropTypes.func,
    updateConfig: PropTypes.func,
  }
@@ -42,7 +43,7 @@
        tabId: tabs.tabId || '',
        parentId: tabs.parentId || '',
        subtype: tabs.subtype,
        setting: {span: 12, position: 'top', tabStyle: 'line', name: tabs.name},
        setting: {span: 24, position: 'top', tabStyle: 'line', name: tabs.name},
        subtabs: [
          { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 1', icon: '', components: [] },
          { uuid: Utils.getuuid(), parentId: tabs.uuid, floor: tabs.floor, label: 'Tab 2', icon: '', components: [] },
@@ -200,7 +201,7 @@
    return (
      <div className="menu-tabs-edit-box">
        <SettingComponent config={tabs} updateConfig={this.updateComponent} />
        {/* <SettingComponent config={tabs} updateConfig={this.updateComponent} /> */}
        <Tabs defaultActiveKey="1" tabPosition={tabs.setting.position} type={tabs.setting.tabStyle}>
          {tabs.subtabs.map((tab, index) => (
            <TabPane tab={
@@ -218,7 +219,19 @@
              <TabComponents config={tab} handleList={this.updateTabComponent} deleteCard={this.deleteCard} />
            </TabPane>
          ))}
          <TabPane className="tab-add" disabled tab={<Icon onClick={this.tabAdd} type="plus" />} key="add"></TabPane>
          <TabPane disabled tab={
            <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
              <div className="mk-popover-control">
                <Icon className="plus" title="add" type="plus" onClick={this.tabAdd} />
                <Icon className="close" title="delete" type="delete" onClick={() => this.props.deleteTabs(tabs.uuid)} />
                <SettingComponent config={tabs} updateConfig={this.updateComponent} />
              </div>
            } trigger="hover">
              <Icon type="tool" />
            </Popover>
          } key="tool">
          </TabPane>
          {/* <TabPane className="tab-add" disabled tab={<Icon onClick={this.tabAdd} type="plus" />} key="add"></TabPane> */}
        </Tabs>
        <Modal
          wrapClassName="popview-modal"
src/menu/components/tabs/antv-tabs/index.scss
@@ -1,9 +1,16 @@
.menu-tabs-edit-box {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
  .ant-tabs-tabpane-active {
    min-height: 200px;
  }
  .ant-tabs-bar {
    margin-bottom: 0px;
  }
  .ant-tabs-content {
    padding-top: 20px;
  }
  .ant-tabs .ant-tabs-left-bar .ant-tabs-tab {
    padding: 0px;
@@ -12,7 +19,7 @@
      display: inline-block;
      padding: 8px 24px;
    }
    .anticon-plus {
    .anticon-tool {
      padding: 8px 24px;
    }
  }
@@ -23,7 +30,7 @@
      display: inline-block;
      padding: 8px 24px;
    }
    .anticon-plus {
    .anticon-tool {
      padding: 8px 24px;
    }
  }
@@ -34,8 +41,9 @@
      display: inline-block;
      padding: 12px 16px;
    }
    .anticon-plus {
      color: #26C281;
    .anticon-tool {
      color: rgba(0, 0, 0, 0.65);
      font-size: 16px;
      padding: 12px 16px;
      margin-right: 0px;
      min-width: 100%;
@@ -51,7 +59,7 @@
        > span {
          padding: 0px 16px;
        }
        .anticon-plus {
        .anticon-tool {
          padding: 0px 16px;
        }
      }
@@ -73,7 +81,7 @@
        padding: 0px;
        border: 0px;
        background: transparent;
        .anticon-plus {
        .anticon-tool {
          padding: 12px 16px;
        }
      }
src/menu/components/tabs/tabcomponents/card.jsx
@@ -40,14 +40,14 @@
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar card={card} updateConfig={updateConfig} />)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} />)
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deleteTabs={delCard} />)
    }
  }
  return (
    <div className={'ant-col mk-component-card ant-col-' + (card.setting ? card.setting.span : 24)} ref={node => drag(drop(node))} style={style}>
      {getCardComponent()}
      <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} />
      {card.type !== 'tabs' ? <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} /> : null}
    </div>
  )
}
src/menu/components/tabs/tabcomponents/index.jsx
@@ -92,7 +92,8 @@
      let names = {
        bar: '柱状图',
        line: '折线图',
        tabs: '标签组'
        tabs: '标签组',
        card: '卡片'
      }
      let i = 1
      
src/menu/datasource/index.jsx
@@ -27,7 +27,6 @@
    const { config } = this.props
    this.setState({setting: fromJS(config.setting).toJS()})
    this.props.updateConfig(config) // 触发菜单信息更新
  }
  shouldComponentUpdate (nextProps, nextState) {
src/menu/menushell/card.jsx
@@ -7,6 +7,7 @@
const AntvBar = asyncComponent(() => import('@/menu/components/chart/antv-bar'))
const AntvTabs = asyncComponent(() => import('@/menu/components/tabs/antv-tabs'))
const DataCard = asyncComponent(() => import('@/menu/components/card/data-card'))
const Card = ({ id, card, moveCard, findCard, delCard, hasDrop, doubleClickCard, updateConfig }) => {
  const originalIndex = findCard(id).index
@@ -40,14 +41,16 @@
    if (card.type === 'bar' || card.type === 'line') {
      return (<AntvBar card={card} updateConfig={updateConfig} />)
    } else if (card.type === 'tabs') {
      return (<AntvTabs tabs={card} updateConfig={updateConfig} />)
      return (<AntvTabs tabs={card} updateConfig={updateConfig} deleteTabs={delCard} />)
    } else if (card.type === 'card') {
      return (<DataCard card={card} updateConfig={updateConfig} />)
    }
  }
  return (
    <div className={'ant-col mk-component-card ant-col-' + (card.setting ? card.setting.span : 12)} ref={node => drag(drop(node))} style={style}>
      {getCardComponent()}
      <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} />
      {card.type !== 'tabs' ? <Icon className="remove-component" title="delete" type="delete" onClick={() => delCard(id)} /> : null}
    </div>
  )
}
src/menu/menushell/index.jsx
@@ -84,7 +84,8 @@
      let names = {
        bar: '柱状图',
        line: '折线图',
        tabs: '标签组'
        tabs: '标签组',
        card: '卡片'
      }
      let i = 1
      
@@ -123,20 +124,22 @@
  })
  return (
    <div ref={drop} className="ant-row menu-shell-inner">
      {cards.map(card => (
        <Card
          id={card.uuid}
          key={card.uuid}
          card={card}
          moveCard={moveCard}
          delCard={deleteCard}
          findCard={findCard}
          hasDrop={hasDrop}
          updateConfig={updateConfig}
          doubleClickCard={doubleClickCard}
        />
      ))}
    <div ref={drop} className="menu-shell-inner" style={menu.style}>
      <div className="ant-row">
        {cards.map(card => (
          <Card
            id={card.uuid}
            key={card.uuid}
            card={card}
            moveCard={moveCard}
            delCard={deleteCard}
            findCard={findCard}
            hasDrop={hasDrop}
            updateConfig={updateConfig}
            doubleClickCard={doubleClickCard}
          />
        ))}
      </div>
      {cards.length === 0 ?
        <Empty description="请添加组件" /> : null
      }
src/menu/menushell/index.scss
@@ -1,9 +1,26 @@
.menu-shell-inner {
  min-height: calc(100vh - 150px);
  margin: -8px;
  padding: 16px;
  width: 100%;
  background-size: 100%;
  >.ant-col {
    padding: 8px;
  >.ant-row {
    margin-left: -4px;
    margin-right: -4px;
    margin-top: -4px;
    >.ant-col {
      padding: 8px;
    }
    > .mk-component-card:hover {
      > .remove-component {
        opacity: 1;
      }
      > div {
        > .model-datasource > .anticon-setting, > .model-menu-tabs-setting > .anticon-setting {
          opacity: 1;
        }
      }
    }
  }
  .anticon {
    cursor: unset;
@@ -24,16 +41,7 @@
      transition: opacity 0.2s;
    }
  }
  > .mk-component-card:hover {
    > .remove-component {
      opacity: 1;
    }
    > div {
      > .model-datasource > .anticon-setting, > .model-menu-tabs-setting > .anticon-setting {
        opacity: 1;
      }
    }
  }
  >.ant-empty {
    padding-top: 150px;
  }
src/menu/modelsource/option.jsx
@@ -5,12 +5,14 @@
import line from '@/assets/mobimg/line.png'
import line1 from '@/assets/mobimg/line1.png'
import tabs from '@/assets/mobimg/tabs.png'
import card1 from '@/assets/mobimg/card1.png'
// const _dict =  sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
// 组件配置信息
export const menuOptions = [
  { type: 'menu', url: tabs, component: 'tabs', subtype: 'tabs' },
  { type: 'menu', url: card1, component: 'card', subtype: 'card1' },
  { type: 'menu', url: line, component: 'line', subtype: 'line' },
  { type: 'menu', url: line1, component: 'line', subtype: 'line1' },
  { type: 'menu', url: bar, component: 'bar', subtype: 'bar' },
src/tabviews/custom/components/chart/antv-bar-line/index.scss
@@ -1,5 +1,6 @@
.custom-line-chart-plot-box {
  margin-bottom: 30px;
  // margin-bottom: 30px;
  background: #ffffff;
  > .chart-header {
    height: 45px;
src/tabviews/custom/components/tabs/antv-tabs/index.scss
@@ -1,4 +1,5 @@
.menu-antv-tabs-wrap {
  position: relative;
  box-sizing: border-box;
  background: #ffffff;
}
src/tabviews/custom/index.jsx
@@ -458,10 +458,10 @@
  render() {
    const { loadingview, viewlost } = this.state
    const { loadingview, viewlost, config } = this.state
    return (
      <div className="custom-page-wrap" id={this.state.ContainerId}>
      <div className="custom-page-wrap" id={this.state.ContainerId} style={config ? config.style : null}>
        {loadingview && <Spin size="large" />}
        <Row gutter={8}>{this.getComponents()}</Row>
        {options.sysType !== 'cloud' ? <Button
src/tabviews/custom/index.scss
@@ -1,14 +1,21 @@
.custom-page-wrap {
  position: relative;
  min-height: calc(100vh - 94px);
  height: 100%;
  padding-top: 16px;
  padding-bottom: 80px;
  padding-left: 16px;
  padding-right: 16px;
  background-size: 100%;
  .box404 {
    padding-top: 30px;
  }
  .ant-col {
    padding-bottom: 16px;
  }
  .ant-modal-mask {
    position: absolute;
  }
src/views/menudesign/index.jsx
@@ -26,7 +26,7 @@
const MenuForm = asyncComponent(() => import('@/menu/menuform'))
const SourceWrap = asyncComponent(() => import('@/menu/modelsource'))
const MenuShell = asyncComponent(() => import('@/menu/menushell'))
// const Controller = asyncComponent(() => import('@/mob/controller'))
const Controller = asyncComponent(() => import('@/menu/bgcontroller'))
// const DataSource = asyncComponent(() => import('@/mob/datasource'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
@@ -202,7 +202,8 @@
            MenuName: this.props.match.params.MenuName,
            MenuNo: this.props.match.params.MenuNo,
            tables: [],
            components: []
            components: [],
            style: {backgroundColor: '#ffffff', backgroundImage: ''}
          }
        } else {
          config.uuid = this.props.match.params.MenuId
@@ -376,9 +377,9 @@
                  <Panel header={dict['mob.component']} key="component">
                    <SourceWrap />
                  </Panel>
                  {/* <Panel header={dict['mob.style']} key="style">
                    <Controller />
                  </Panel> */}
                  <Panel header={'背景'} key="background">
                    {config ? <Controller config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
                </Collapse>
              </div>
              <div className="menu-view">
src/views/menudesign/index.scss
@@ -107,6 +107,7 @@
      > .ant-card {
        >.ant-card-head {
          margin-bottom: 0px;
          .ant-card-head-title {
            color: #1890ff;
            padding: 5px 0;
@@ -132,7 +133,7 @@
          }
        }
        >.ant-card-body {
          padding: 20px;
          padding: 0px;
        }
      }
    }