king
2019-11-05 78893aac37ff8bdc2ef339d91f383e40aa530300
update-header
7个文件已修改
4个文件已添加
1015 ■■■■■ 已修改文件
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/dragelement/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/dragelement/index.scss 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/editmenu/index.jsx 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/editmenu/index.scss 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.jsx 390 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/header/index.scss 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/preview/index.jsx 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/preview/index.scss 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.jsx 83 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/sidemenu/index.scss 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -77,7 +77,7 @@
    "workbox-webpack-plugin": "4.3.1"
  },
  "scripts": {
    "dev": "set PORT=3001 && node scripts/start.js --host 192.168.8.106",
    "dev": "set PORT=3001 && node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js"
  },
src/components/header/dragelement/index.jsx
@@ -61,12 +61,14 @@
          findCard={findCard}
        />
      ))}
      <div className="card-add" onClick={add}>
        <Icon type="plus" />
      <div className="btn-group">
        <div className="card-add" onClick={add}>
          <Icon type="plus" />
        </div>
        <Button type="primary" onClick={thawmenu}>{dict['header.thawmenu']}</Button>
        <Button type="primary" onClick={confirm}>{dict['header.confirm']}</Button>
        <Button onClick={cancel}>{dict['header.close']}</Button>
      </div>
      <Button type="primary" onClick={thawmenu}>{dict['header.thawmenu']}</Button>
      <Button type="primary" onClick={confirm}>{dict['header.confirm']}</Button>
      <Button onClick={cancel}>{dict['header.close']}</Button>
    </div>
  )
}
src/components/header/dragelement/index.scss
@@ -21,6 +21,9 @@
    padding: 0 10px;
    height: 26px;
  }
  .btn-group {
    display: inline-block;
  }
}
.card {
  position: relative;
@@ -47,6 +50,7 @@
    }
  }
  .edit {
    display: none;
    position: absolute;
    right: 0;
    bottom: 0;
@@ -56,3 +60,8 @@
    }
  }
}
.card:hover {
  .edit {
    display: inline-block;
  }
}
src/components/header/editmenu/index.jsx
New file
@@ -0,0 +1,373 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Button, Spin } from 'antd'
import TransferForm from '@/components/transferform'
import DragElement from '../dragelement'
import MenuForm from '../menuform'
import Api from '@/api'
import zhCN from '@/locales/zh-CN/header.js'
import enUS from '@/locales/en-US/header.js'
import './index.scss'
const { confirm } = Modal
let previewList = null
class EditMenu extends Component {
  static propTpyes = {
    menulist: PropTypes.any,
    reload: PropTypes.func,
    exitEdit: PropTypes.func
  }
  state = {
    thawmenulist: null, // 已冻结的一级菜单
    addMvisible: null,
    editMenu: null, // 编辑菜单
    editMvisible: false, // 编辑菜单模态框
    thawMvisible: false, // 解除冻结模态框
    confirmLoading: false, // 提交中。。。
    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
  }
  handlePreviewList = (List) => {
    // 菜单顺序改变时,保存中间状态
    previewList = List
  }
  editMenuModal = (Menu) => {
    // 菜单编辑:修改
    const menu = fromJS(Menu).toJS()
    if (previewList && !is(fromJS(previewList), fromJS(this.props.menulist))) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.presave'],
        duration: 10
      })
    } else {
      this.setState({
        editMvisible: true,
        editMenu: menu.card
      })
    }
  }
  editMemuSubmit = () => {
    // 编辑菜单:提交
    this.editMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Upt'
      this.setState({
        confirmLoading: true
      })
      Api.submitInterface(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            editMvisible: false,
            editMenu: null
          })
          this.props.reload()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    }, () => {})
  }
  editMemuCancel = () => {
    // 编辑菜单:取消
    this.setState({
      confirmLoading: false,
      editMvisible: false,
      editMenu: null
    })
  }
  addMemuSubmit = () => {
    // 新建菜单:提交
    this.addMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Add'
      param.Sort = (this.state.menulist.length + 1) * 10
      this.setState({
        confirmLoading: true
      })
      Api.submitInterface(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            addMvisible: false,
            menulist: null
          })
          this.addMenuFormRef.handleReset('add')
          this.props.reload()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    }, () => {})
  }
  addMemuCancel = () => {
    // 新建菜单:取消
    this.setState({
      confirmLoading: false,
      addMvisible: false
    })
    this.addMenuFormRef.handleReset('add')
  }
  deleteMemu = () => {
    let _this = this
    confirm({
      title: this.state.dict['header.menu.close'].replace('@M', this.state.editMenu.MenuName),
      content: '',
      okText: this.state.dict['header.confirm'],
      cancelText: this.state.dict['header.cancel'],
      onOk() {
        let param = {
          func: 'sPC_MainMenu_Del',
          MenuID: _this.state.editMenu.MenuID
        }
        return Api.submitInterface(param).then(res => {
          if (res.status) {
            _this.setState({
              editMvisible: false,
              editMenu: null,
              menulist: null
            })
            _this.props.reload()
          } else {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 10
            })
          }
        })
      },
      onCancel() {}
    })
  }
  thawMemuSubmit = () => {
    if (this.refs.trawmenu.state.targetKeys.length === 0) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.thawmenu.select'],
        duration: 10
      })
    } else {
      this.setState({
        confirmLoading: true
      })
      let defers = this.refs.trawmenu.state.targetKeys.map(item => {
        return new Promise((resolve) => {
          Api.submitInterface({
            func: 'sPC_MainMenu_ReDel',
            MenuID: item
          }).then(res => {
            if (res.status) {
              resolve('')
            } else {
              resolve(res.message)
            }
          })
        })
      })
      Promise.all(defers).then(res => {
        let msg = res.filter(Boolean)[0]
        if (msg) {
          notification.error({
            top: 92,
            message: msg,
            duration: 15
          })
        } else {
          this.setState({
            confirmLoading: false,
            thawMvisible: false,
            thawmenulist: null
          })
          this.props.reload()
        }
      })
    }
  }
  thawMemuCancel = () => {
    this.setState({
      thawMvisible: false,
      thawmenulist: null
    })
  }
  handleButton = (type) => {
    // 菜单编辑:添加,确定,取消
    let _menuchange = previewList && !is(fromJS(previewList), fromJS(this.props.menulist))
    if ((type === 'add' || type === 'thawmenu') && _menuchange) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.presave'],
        duration: 10
      })
    } else if (type === 'add') {
      this.setState({
        addMvisible: true
      })
    } else if (type === 'confirm' && _menuchange) {
      let _this = this
      let param  = {}
      param.func = 'sPC_Menu_SortUpt'
      param.LText = []
      previewList.forEach((item, index) => {
        param.LText.push('selectmspace\'' + item.MenuID + '\'mspaceasmspaceMenuid,' + (index + 1) * 10 + 'mspaceasmspacesort')
      })
      param.LText = param.LText.join('mspaceunionmspace')
      confirm({
        title: this.state.dict['header.menu.resetorder'],
        content: '',
        okText: this.state.dict['header.confirm'],
        cancelText: this.state.dict['header.cancel'],
        onOk() {
          return Api.submitInterface(param).then(res => {
            if (res.status) {
              _this.props.reload()
            } else {
              notification.warning({
                top: 92,
                message: res.message,
                duration: 10
              })
            }
          })
        },
        onCancel() {}
      })
    } else if (type === 'thawmenu') {
      this.setState({
        thawMvisible: true
      })
      Api.submitInterface({
        func: 'sPC_Get_FrozenMenu',
        ParentID: '0',
        TYPE: 10
      }).then(res => {
        if (res.status) {
          this.setState({
            thawmenulist: res.data.map(menu => {
              return {
                key: menu.MenuID,
                title: menu.MenuName
              }
            })
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    } else {
      this.props.exitEdit()
    }
  }
  UNSAFE_componentWillMount () {
    previewList = null
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.menulist), fromJS(nextProps.menulist))) {
      previewList = null
    }
  }
  render () {
    return (
      <div className="header-edit-box">
        <div className="mask"></div>
        {this.props.menulist && <DndProvider backend={HTML5Backend}>
          <DragElement
            dict={this.state.dict}
            list={this.props.menulist}
            handlePreviewList={this.handlePreviewList}
            handleMenu={this.editMenuModal}
            handleButton={this.handleButton}
          />
        </DndProvider>}
        {/* 新建菜单模态框 */}
        <Modal
          title={this.state.dict['header.menu.addtitle']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.addMvisible}
          onOk={this.addMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.addMemuCancel}
        >
          <MenuForm
            dict={this.state.dict}
            type="add"
            menu={null}
            wrappedComponentRef={(inst) => this.addMenuFormRef = inst}
          />
        </Modal>
        {/* 解除冻结菜单模态框 */}
        <Modal
          title={this.state.dict['header.thawmenu']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.thawMvisible}
          onOk={this.thawMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.thawMemuCancel}
        >
          {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
          {this.state.thawmenulist && <TransferForm ref="trawmenu" dict={this.state.dict} menulist={this.state.thawmenulist}/>}
        </Modal>
        {/* 编辑菜单模态框 */}
        <Modal
          title={this.state.dict['header.menu.editTitle']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.editMvisible}
          footer={null}
          onCancel={this.editMemuCancel}
        >
          <MenuForm
            dict={this.state.dict}
            type="edit"
            menu={this.state.editMenu}
            wrappedComponentRef={(inst) => this.editMenuFormRef = inst}
          />
          <div className="edit-modal-footer">
            <Button onClick={this.editMemuCancel}>{this.state.dict['header.cancel']}</Button>
            <Button type="primary" onClick={this.editMemuSubmit} loading={this.state.confirmLoading}>{this.state.dict['header.confirm']}</Button>
            <Button type="danger" onClick={this.deleteMemu}>{this.state.dict['header.delete']}</Button>
          </div>
        </Modal>
      </div>
    )
  }
}
export default EditMenu
src/components/header/editmenu/index.scss
New file
@@ -0,0 +1,10 @@
.header-edit-box {
  .mask {
    position: fixed;
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    background-color: rgba(0, 0, 0, 0.25);
  }
}
src/components/header/index.jsx
@@ -3,15 +3,11 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import {Dropdown, Menu, Icon, Modal, message, Form, notification, Button, Switch, Spin } from 'antd'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import {Dropdown, Menu, Icon, Modal, message, Form, notification, Switch } from 'antd'
import md5 from 'md5'
import asyncComponent from '@/utils/asyncComponent'
import {toggleCollapse, modifyMainMenu, resetState, resetDebug, resetEditState, resetEditLevel} from '@/store/action'
import Resetpwd from '@/components/resetpwd'
import TransferForm from '@/components/transferform'
import MenuForm from './menuform'
import DragElement from './dragelement'
import Api from '@/api'
import zhCN from '@/locales/zh-CN/header.js'
import enUS from '@/locales/en-US/header.js'
@@ -20,8 +16,8 @@
import avatar from '../../assets/img/avatar.jpg'
import './index.scss'
const EditMenu = asyncComponent(() => import('./editmenu'))
const { confirm } = Modal
let previewList = null
class Header extends Component {
  static propTpyes = {
@@ -33,12 +29,7 @@
  }
  state = {
    menulist: null, // 一级菜单
    thawmenulist: null, // 已冻结的一级菜单
    visible: false, // 修改密码模态框
    addMvisible: false, // 添加菜单模态框
    editMenu: null, // 编辑菜单
    editMvisible: false, // 编辑菜单模态框
    thawMvisible: false, // 解除冻结模态框
    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
    confirmLoading: false,
    userName: localStorage.getItem('username')
@@ -167,123 +158,30 @@
        this.props.modifyMainMenu(result.data[0])
      }
      previewList = result.data.map((item, index) => {
        item.id = index
        item.text = item.MenuName
        if (item.PageParam) {
          try {
            item.PageParam = JSON.parse(item.PageParam)
          } catch (e) {
      this.setState({
        menulist: result.data.map((item, index) => {
          item.id = index
          item.text = item.MenuName
          if (item.PageParam) {
            try {
              item.PageParam = JSON.parse(item.PageParam)
            } catch (e) {
              item.PageParam = {OpenType: 'menu', linkUrl: ''}
            }
          } else {
            item.PageParam = {OpenType: 'menu', linkUrl: ''}
          }
        } else {
          item.PageParam = {OpenType: 'menu', linkUrl: ''}
        }
        return item
      })
      this.setState({
        menulist: previewList
          return item
        })
      })
    }
  }
  handlePreviewList = (List) => {
    // 菜单顺序改变时,保存中间状态
    previewList = List
  }
  handleButton = (type) => {
    // 菜单编辑:添加,确定,取消
    if ((type === 'add' || type === 'thawmenu') && !is(fromJS(previewList), fromJS(this.state.menulist))) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.presave'],
        duration: 10
      })
    } else if (type === 'add') {
      this.setState({
        addMvisible: true
      })
    } else if (type === 'confirm' && !is(fromJS(previewList), fromJS(this.state.menulist))) {
      let _this = this
      let param  = {}
      param.func = 'sPC_Menu_SortUpt'
      param.LText = []
      previewList.forEach((item, index) => {
        param.LText.push('selectmspace\'' + item.MenuID + '\'mspaceasmspaceMenuid,' + (index + 1) * 10 + 'mspaceasmspacesort')
      })
      param.LText = param.LText.join('mspaceunionmspace')
      confirm({
        title: this.state.dict['header.menu.resetorder'],
        content: '',
        okText: this.state.dict['header.confirm'],
        cancelText: this.state.dict['header.cancel'],
        onOk() {
          return Api.submitInterface(param).then(res => {
            if (res.status) {
              _this.setState({
                menulist: null
              })
              _this.loadmenu()
            } else {
              notification.warning({
                top: 92,
                message: res.message,
                duration: 10
              })
            }
          })
        },
        onCancel() {}
      })
    } else if (type === 'thawmenu') {
      this.setState({
        thawMvisible: true
      })
      Api.submitInterface({
        func: 'sPC_Get_FrozenMenu',
        ParentID: '0',
        TYPE: 10
      }).then(res => {
        if (res.status) {
          this.setState({
            thawmenulist: res.data.map(menu => {
              return {
                key: menu.MenuID,
                title: menu.MenuName
              }
            })
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    } else {
      previewList = this.state.menulist
      this.props.resetEditLevel(false)
    }
  }
  handleMenu = (Menu) => {
    // 菜单编辑:修改
    const menu = fromJS(Menu).toJS()
    if (!is(fromJS(previewList), fromJS(this.state.menulist))) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.presave'],
        duration: 10
      })
    } else {
      this.setState({
        editMvisible: true,
        editMenu: menu.card
      })
    }
  reload = () => {
    this.setState({
      menulist: null
    })
    this.loadmenu()
  }
  changeEditState = (state) => {
@@ -291,178 +189,23 @@
    this.props.resetEditState(state)
  }
  addMemuSubmit = () => {
    // 新建菜单:提交
    this.addMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Add'
      param.Sort = (this.state.menulist.length + 1) * 10
      this.setState({
        confirmLoading: true
      })
      Api.submitInterface(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            addMvisible: false,
            menulist: null
          })
          this.addMenuFormRef.handleReset('add')
          this.loadmenu()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    }, () => {})
  }
  addMemuCancel = () => {
    // 新建菜单:取消
    this.setState({
      confirmLoading: false,
      addMvisible: false
    })
    this.addMenuFormRef.handleReset('add')
  }
  editMemuSubmit = () => {
    // 编辑菜单:提交
    this.editMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Upt'
      this.setState({
        confirmLoading: true
      })
      Api.submitInterface(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            editMvisible: false,
            editMenu: null,
            menulist: null
          })
          this.loadmenu()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 10
          })
        }
      })
    }, () => {})
  }
  editMemuCancel = () => {
    // 编辑菜单:取消
    this.setState({
      confirmLoading: false,
      editMvisible: false,
      editMenu: null
    })
  }
  deleteMemu = () => {
    let _this = this
    confirm({
      title: this.state.dict['header.menu.close'].replace('@M', this.state.editMenu.MenuName),
      content: '',
      okText: this.state.dict['header.confirm'],
      cancelText: this.state.dict['header.cancel'],
      onOk() {
        let param = {
          func: 'sPC_MainMenu_Del',
          MenuID: _this.state.editMenu.MenuID
        }
        return Api.submitInterface(param).then(res => {
          if (res.status) {
            _this.setState({
              editMvisible: false,
              editMenu: null,
              menulist: null
            })
            _this.loadmenu()
          } else {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 10
            })
          }
        })
      },
      onCancel() {}
    })
  }
  thawMemuSubmit = () => {
    if (this.refs.trawmenu.state.targetKeys.length === 0) {
      notification.warning({
        top: 92,
        message: this.state.dict['header.menu.thawmenu.select'],
        duration: 10
      })
    } else {
      this.setState({
        confirmLoading: true
      })
      let defers = this.refs.trawmenu.state.targetKeys.map(item => {
        return new Promise((resolve) => {
          Api.submitInterface({
            func: 'sPC_MainMenu_ReDel',
            MenuID: item
          }).then(res => {
            if (res.status) {
              resolve('')
            } else {
              resolve(res.message)
            }
          })
        })
      })
      Promise.all(defers).then(res => {
        let msg = res.filter(Boolean)[0]
        if (msg) {
          notification.error({
            top: 92,
            message: msg,
            duration: 15
          })
        } else {
          this.setState({
            confirmLoading: false,
            thawMvisible: false,
            thawmenulist: null,
            menulist: null
          })
          this.loadmenu()
        }
      })
    }
  }
  thawMemuCancel = () => {
    this.setState({
      thawMvisible: false,
      thawmenulist: null
    })
  }
  enterEdit = () => {
    // 进入编辑状态
    this.props.resetEditLevel('level1')
  }
  exitEdit = () => {
    // 退出编辑状态
    this.props.resetEditLevel(false)
  }
  
  UNSAFE_componentWillMount () {
    // 组件加载时,获取菜单数据
    this.loadmenu()
  }
  UNSAFE_componentWillReceiveProps () {
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -488,29 +231,21 @@
          <Icon type={this.props.collapse ? 'menu-unfold' : 'menu-fold'} />
        </div>
        {/* 正常菜单 */}
        {this.props.editLevel !== 'level1' && this.state.menulist && <ul className="header-menu">{
        {this.props.editLevel !== 'level1' && this.state.menulist &&
        <ul className="header-menu">{
          this.state.menulist.map(item => {
            return (
              <li key={item.MenuID} onClick={() => {this.changeMenu(item)}} className={this.props.selectmenu.MenuID === item.MenuID ? 'active' : ''}>
                {item.MenuName}
              </li>
            )
          })
        }</ul>}
          })}
        </ul>}
        {/* 进入编辑按钮 */}
        {this.props.editState && !this.props.editLevel && <Icon onClick={this.enterEdit} className="edit-check" type="edit" />}
        {/* 编辑菜单 */}
        {this.props.editLevel === 'level1' && this.state.menulist && <DndProvider className="header-drag-menu" backend={HTML5Backend}>
          <DragElement
            dict={this.state.dict}
            list={this.state.menulist}
            handlePreviewList={this.handlePreviewList}
            handleMenu={this.handleMenu}
            handleButton={this.handleButton}
          />
        </DndProvider>}
        {/* 编辑mask */}
        <div className={'mask ' + (this.props.editLevel === 'level1' ? 'active' : '')}></div>
        {this.props.editLevel === 'level1' && <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/>}
        {/* 头像、用户名 */}
        <Dropdown className="header-setting" overlay={menu}>
          <div>
            <img src={avatar} alt=""/>
@@ -530,57 +265,6 @@
          onCancel={this.handleCancel}
        >
          <Resetpwd dict={this.state.dict} wrappedComponentRef={(inst) => this.formRef = inst} resetPwdSubmit={this.resetPwdSubmit}/>
        </Modal>
        {/* 新建菜单模态框 */}
        <Modal
          title={this.state.dict['header.menu.addtitle']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.addMvisible}
          onOk={this.addMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.addMemuCancel}
        >
          <MenuForm
            dict={this.state.dict}
            type="add"
            menu={null}
            wrappedComponentRef={(inst) => this.addMenuFormRef = inst}
          />
        </Modal>
        {/* 编辑菜单模态框 */}
        <Modal
          title={this.state.dict['header.menu.editTitle']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.editMvisible}
          footer={null}
          onCancel={this.editMemuCancel}
        >
          <MenuForm
            dict={this.state.dict}
            type="edit"
            menu={this.state.editMenu}
            wrappedComponentRef={(inst) => this.editMenuFormRef = inst}
          />
          <div className="edit-modal-footer">
            <Button onClick={this.editMemuCancel}>{this.state.dict['header.cancel']}</Button>
            <Button type="primary" onClick={this.editMemuSubmit} loading={this.state.confirmLoading}>{this.state.dict['header.confirm']}</Button>
            <Button type="danger" onClick={this.deleteMemu}>{this.state.dict['header.delete']}</Button>
          </div>
        </Modal>
        {/* 解除冻结菜单模态框 */}
        <Modal
          title={this.state.dict['header.thawmenu']}
          okText={this.state.dict['header.confirm']}
          cancelText={this.state.dict['header.cancel']}
          visible={this.state.thawMvisible}
          onOk={this.thawMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.thawMemuCancel}
        >
          {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
          {this.state.thawmenulist && <TransferForm ref="trawmenu" dict={this.state.dict} menulist={this.state.thawmenulist}/>}
        </Modal>
      </header>
    )
src/components/header/index.scss
@@ -85,27 +85,28 @@
      }
    }
  }
  .header-drag-menu {
    float: left;
  }
  // .header-drag-menu {
  //   float: left;
  // }
  .edit-check {
    font-size: 18px;
    margin-top: 14px;
    margin-left: 10px;
    cursor: pointer;
  }
  .mask {
    position: fixed;
    top: 48px;
    left: 0px;
    right: 0px;
    bottom: calc(100vh - 48px);
    transition: bottom 0.1s;
  }
  .mask.active {
    bottom: 0px;
    background-color: rgba(0, 0, 0, 0.15);
  }
  // .mask {
  //   position: fixed;
  //   top: 48px;
  //   left: 0px;
  //   right: 0px;
  //   bottom: calc(100vh - 48px);
  //   background-color: rgba(0, 0, 0, 0);
  //   transition: background-color 0.5s;
  // }
  // .mask.active {
  //   bottom: 0px;
  //   background-color: rgba(0, 0, 0, 0.25);
  // }
}
.header-dropdown {
  li {
src/components/preview/index.jsx
New file
@@ -0,0 +1,57 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Button} from 'antd'
import './index.scss'
class Preview extends Component {
  static propTpyes = {
    preview: PropTypes.any,
    cancel: PropTypes.func
  }
  state = {
    show: false,
    url: ''
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (nextProps.preview) {
      this.setState({
        url: nextProps.preview
      })
      setTimeout(() => {
        this.setState({
          show: true
        })
      }, 10)
    } else {
      this.setState({
        show: false
      })
      setTimeout(() => {
        this.setState({
          url: ''
        })
      }, 500)
    }
  }
  close = () => {
    this.props.cancel()
  }
  render () {
    return (
      <div>
        {this.state.url &&
          <div className={'preview-box ' + (this.state.show ? 'active' : '')} onClick={this.close}>
            <Button shape="circle" icon="close" />
            {this.state.url && <img src={this.state.url} alt=""/>}
          </div>
        }
      </div>
    )
  }
}
export default Preview
src/components/preview/index.scss
New file
@@ -0,0 +1,25 @@
.preview-box {
  position: fixed;
  z-index: 1100;
  left: 0;
  right: 0px;
  top: 0px;
  bottom: 0px;
  background: rgba($color: #000000, $alpha: 0.6);
  line-height: 100vh;
  text-align: center;
  opacity: 0;
  transition: opacity 0.5s;
  img {
    max-width: 80vw;
    max-height: 90vh;
  }
  button {
    position: absolute;
    top: 4vh;
    right: 4vw;
  }
}
.active {
  opacity: 1;
}
src/components/sidemenu/index.jsx
@@ -3,18 +3,20 @@
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Menu, Icon, Button, notification, Modal, Spin, Tabs, Radio, Card, Row, Col} from 'antd'
// import { Menu, Icon, Button, notification, Modal, Spin, Tabs, Card, Row, Col} from 'antd'
import { Menu, Icon, Button, notification, Modal, Spin, Tabs} from 'antd'
import HTML5Backend from 'react-dnd-html5-backend'
import { DndProvider } from 'react-dnd'
import {modifyTabview, resetEditLevel} from '@/store/action'
import TransferForm from '@/components/transferform'
import Preview from '@/components/preview'
import DragElement from './dragelement'
import MenuForm from './menuform'
import zhCN from '@/locales/zh-CN/header.js'
import enUS from '@/locales/en-US/header.js'
import Api from '@/api'
import './index.scss'
import nortable from '@/assets/img/normaltable.jpg'
// import nortable from '@/assets/img/normaltable.jpg'
const { SubMenu } = Menu
const { confirm } = Modal
@@ -48,7 +50,8 @@
    thawmenulist: null,
    createThirdMenu: false,
    dict: (!localStorage.getItem('lang') || localStorage.getItem('lang') === 'zh-CN') ? zhCN : enUS,
    openKeys: null
    openKeys: null,
    preview: null
  }
  async loadsubmenu (menu) {
@@ -586,6 +589,18 @@
    })
  }
  previewPicture = (url) => {
    this.setState({
      preview: url
    })
  }
  cancelPrePicture = () => {
    this.setState({
      preview: null
    })
  }
  render () {
    const editShow = (this.props.editState && !this.props.editLevel) || false
    return (
@@ -687,10 +702,11 @@
          {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
          {this.state.thawmenulist && <TransferForm ref="trawmenu" dict={this.state.dict} menulist={this.state.thawmenulist}/>}
        </Modal>
        {this.props.editLevel === 'level3' && this.state.createThirdMenu && <div className="editboard">
        {/* {this.props.editLevel === 'level3' && this.state.createThirdMenu &&
        <div className="editboard">
          <div className="workplace">
            <Tabs defaultActiveKey="1" onChange={this.callback}>
              <TabPane tab="新建菜单" key="1">
              <TabPane tab="系统模板" key="1">
                <Row>
                  <Col span={8}>
                    <Card
@@ -699,7 +715,7 @@
                      }>
                      <img src={nortable} alt=""/>
                      <div className="card-operation">
                        <Button type="primary">预览</Button>
                        <Button type="primary" onClick={() => {this.previewPicture(nortable)}}>预览</Button>
                        <Button type="primary" onClick={() => {this.createThMenu()}}>使用模板</Button>
                      </div>
                    </Card>
@@ -711,31 +727,54 @@
                      }>
                      <img src={nortable} alt=""/>
                      <div className="card-operation">
                        <Button type="primary">预览</Button>
                        <Button type="primary" onClick={() => {this.previewPicture(nortable)}}>预览</Button>
                        <Button type="primary" onClick={() => {this.createThMenu()}}>使用模板</Button>
                      </div>
                    </Card>
                  </Col>
                </Row>
              </TabPane>
              {/* <TabPane tab="三级菜单" key="2">
                <Card
                  // className="level2-left"
                  title={
                    <div>
                      <Radio.Group name="radiogroup" defaultValue={1}>
                        <Radio value={1}>排序</Radio>
                        <Radio value={2}>编辑</Radio>
                      </Radio.Group>
                      <Icon onClick={this.enterEdit} className="edit-check" type="plus" />
                    </div>
                  }>
                  <img src={nortable} alt=""/>
                </Card>
              </TabPane> */}
              <TabPane tab="自定义模板" key="2">
                <Row>
                  <Col span={8}>
                    <Card
                      title={
                        '基础表格'
                      }>
                      <img src={nortable} alt=""/>
                      <div className="card-operation">
                        <Button type="primary" onClick={() => {this.previewPicture(nortable)}}>预览</Button>
                        <Button type="primary" onClick={() => {this.createThMenu()}}>使用模板</Button>
                      </div>
                    </Card>
                  </Col>
                  <Col span={8}>
                    <Card
                      title={
                        '数据表格'
                      }>
                      <img src={nortable} alt=""/>
                      <div className="card-operation">
                        <Button type="primary" onClick={() => {this.previewPicture(nortable)}}>预览</Button>
                        <Button type="primary" onClick={() => {this.createThMenu()}}>使用模板</Button>
                      </div>
                    </Card>
                  </Col>
                </Row>
              </TabPane>
            </Tabs>
          </div>
        </div>} */}
        {<div className="editboard">
          <div className="workplace">
            <Tabs defaultActiveKey="1">
              <TabPane tab="编辑模板" key="1">
              </TabPane>
            </Tabs>
          </div>
        </div>}
        <Preview cancel={this.cancelPrePicture} preview={this.state.preview}/>
      </aside>
    )
  }
src/components/sidemenu/index.scss
@@ -88,6 +88,9 @@
      .ant-col {
        padding: 10px;
      }
      .ant-card-head-title {
        text-align: center;
      }
      .ant-card-body {
        padding: 2px;
        position: relative;
@@ -95,25 +98,23 @@
        overflow: hidden;
        .card-operation {
          position: absolute;
          left: 0px;
          right: 0px;
          bottom: 0px;
          top: 100%;
          background: rgba(0, 0, 0, 0.35);
          padding-top: 0;
          transition: top 0.3s, padding-top 0.3s;
          button:first-child {
            margin-right: 10px;
          }
          top: 0;
          height: 0px;
          overflow: hidden;
          transition: height 0.3s;
          button {
            height: 30px;
            padding: 0 10px;
            margin-top: 5px;
            margin-right: 10px;
            display: none;
          }
        }
      }
      .ant-card-body:hover {
        .card-operation {
          top: 0;
          padding-top: 24%;
          height: 40px;
          button {
            display: inline-block;
          }