king
2022-11-21 f6626b05f1275cc2f8ca77f773d4f6a6af1b0a89
src/views/menudesign/index.jsx
@@ -4,7 +4,7 @@
import { is, fromJS } from 'immutable'
import moment from 'moment'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography } from 'antd'
import { ConfigProvider, notification, Modal, Collapse, Card, Switch, Button, Typography, Spin } from 'antd'
import { DoubleLeftOutlined, DoubleRightOutlined, EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'
import html2canvas from 'html2canvas'
import md5 from 'md5'
@@ -12,10 +12,9 @@
import Api from '@/api'
import options from '@/store/options.js'
import Utils, { setGLOBFuncs } from '@/utils/utils.js'
// import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import MKEmitter from '@/utils/events.js'
import MenuUtils from '@/utils/utils-custom.js'
import { getTables } from '@/utils/utils-custom.js'
import asyncComponent from '@/utils/asyncComponent'
import '@/assets/css/design.scss'
@@ -28,6 +27,7 @@
const MenuForm = asyncComponent(() => import('./menuform'))
const HomeForm = asyncComponent(() => import('./homeform'))
const PopView = asyncComponent(() => import('./popview'))
const Header = asyncComponent(() => import('@/menu/header'))
const MenuShell = asyncComponent(() => import('@/menu/menushell'))
const PrintMenuForm = asyncComponent(() => import('./printmenuform'))
@@ -59,16 +59,16 @@
    MenuName: '',
    MenuNo: '',
    delButtons: [],
    copyButtons: [],
    activeKey: 'basedata',
    menuloading: false,
    oriConfig: null,
    config: null,
    customComponents: [],
    comloading: false,
    settingshow: true,
    settingshow: sessionStorage.getItem('settingshow') !== 'false',
    eyeopen: false,
    modalStatus: false       // 弹窗是否开启,判断ctrl+s是否可用
    view: '',
    popConfig: null,
    needUpdate: false
  }
  UNSAFE_componentWillMount() {
@@ -84,7 +84,7 @@
      this.setState({
        MenuType: param.MenuType,
        MenuId: param.MenuId,
        MenuId: param.MenuId || param.MenuID,
        ParentId: param.ParentId || '',
        MenuName: param.MenuName || '',
        MenuNo: param.MenuNo || '',
@@ -105,9 +105,6 @@
  }
  componentDidMount () {
    MKEmitter.addListener('delButtons', this.delButtons)
    MKEmitter.addListener('modalStatus', this.modalStatus)
    MKEmitter.addListener('copyButtons', this.copyButtons)
    MKEmitter.addListener('changePopview', this.initPopview)
    MKEmitter.addListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.addListener('updateCustomComponent', this.updateCustomComponent)
@@ -145,16 +142,32 @@
      let _shortcut = `${preKey}+${keyCode}`
      if (_shortcut === 'ctrl+83') {
        if (this.state.modalStatus) {
        let modals = document.querySelectorAll('.mk-pop-modal')
        let msg = null
        for (let i = 0; i < modals.length; i++) {
          if (msg) {
            break
          }
          let node = modals[i].querySelector('.mk-com-name')
          if (node) {
            msg = node.innerText
          }
        }
        if (msg) {
          notification.warning({
            top: 92,
            message: '请保存' + this.state.modalStatus,
            message: '请保存' + msg,
            duration: 5
          })
          return false
        }
        let node = document.getElementById('save-modal-config')
        if (!node) {
          node = document.getElementById('save-pop-config')
        }
        if (!node) {
          node = document.getElementById('save-config')
        }
@@ -174,20 +187,38 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('delButtons', this.delButtons)
    MKEmitter.removeListener('modalStatus', this.modalStatus)
    MKEmitter.removeListener('copyButtons', this.copyButtons)
    MKEmitter.removeListener('changePopview', this.initPopview)
    MKEmitter.removeListener('triggerMenuSave', this.triggerMenuSave)
    MKEmitter.removeListener('updateCustomComponent', this.updateCustomComponent)
  }
  modalStatus = (val) => {
    this.setState({modalStatus: val})
  triggerMenuSave = () => {
    if (this.state.view === 'popview') return
    this.submitConfig()
  }
  triggerMenuSave = () => {
    this.submitConfig()
  submitPopConfig = (btnconfig) => {
    let parents = {[btnconfig.ParentId]: true}
    let popbtns = {[btnconfig.uuid]: fromJS(btnconfig).toJS()}
    let config = fromJS(this.state.config).toJS()
    config.components = this.setPopView(config.components, parents, popbtns)
    this.setState({ config }, () => {
      this.submitConfig()
    })
  }
  closePop = () => {
    const {config} = this.state
    sessionStorage.setItem('editMenuType', 'menu')
    window.GLOB.urlFields = config.urlFields || []
    window.GLOB.customMenu = config
    this.setState({view: '', popConfig: null})
  }
  getPrintTemp = () => {
@@ -235,41 +266,39 @@
  }
  getAppPictures = () => {
    if (sessionStorage.getItem('app_videos') || sessionStorage.getItem('app_pictures')) return
    if (sessionStorage.getItem('app_pictures')) return
    
    Api.getSystemConfig({
    let deffers = []
    let param = {
      func: 's_url_db_adduptdel',
      PageIndex: 0,  // 0 代表全部
      PageSize: 0,   // 0 代表全部
      typecharone: 'image',
      type: 'search'
    }).then(res => {
      if (res.status) {
        sessionStorage.setItem('app_pictures', JSON.stringify(res.data || []))
      }
    }
    deffers = [new Promise(resolve => {
      setTimeout(() => {
        Api.getSystemConfig({...param, typecharone: 'image'}).then(res => {
          resolve(res.data)
        })
      }, 500)
    }), new Promise(resolve => {
      setTimeout(() => {
        Api.getSystemConfig({...param, typecharone: 'video'}).then(res => {
          resolve(res.data)
        })
      }, 1000)
    }), new Promise(resolve => {
      setTimeout(() => {
        Api.getSystemConfig({...param, typecharone: 'color'}).then(res => {
          resolve(res.data)
        })
      }, 1500)
    })]
      Api.getSystemConfig({
        func: 's_url_db_adduptdel',
        PageIndex: 0,  // 0 代表全部
        PageSize: 0,   // 0 代表全部
        typecharone: 'video',
        type: 'search'
      }).then(res => {
        if (res.status) {
          sessionStorage.setItem('app_videos', JSON.stringify(res.data || []))
        }
      })
      Api.getSystemConfig({
        func: 's_url_db_adduptdel',
        PageIndex: 0,  // 0 代表全部
        PageSize: 0,   // 0 代表全部
        typecharone: 'color',
        type: 'search'
      }).then(res => {
        if (res.status) {
          sessionStorage.setItem('app_colors', JSON.stringify(res.data || []))
        }
      })
    Promise.all(deffers).then(response => {
      sessionStorage.setItem('app_pictures', JSON.stringify(response[0] || []))
      sessionStorage.setItem('app_videos', JSON.stringify(response[1] || []))
      sessionStorage.setItem('app_colors', JSON.stringify(response[2] || []))
    })
  }
@@ -321,31 +350,41 @@
    this.setState({customComponents: coms})
  }
  delButtons = (items) => {
    this.setState({ delButtons: [...this.state.delButtons, ...items] })
  }
  copyButtons = (items) => {
    this.setState({copyButtons: [...this.state.copyButtons, ...items]})
  }
  initPopview = (card, btn) => {
    const { oriConfig, config } = this.state
    const { config } = this.state
    if (!is(fromJS(oriConfig), fromJS(config))) {
    if (!this.checkBase()) {
      notification.warning({
        top: 92,
        message: '配置已修改,请保存!',
        message: '请完善基本信息!',
        duration: 5
      })
      return
    }
    let _btn = fromJS(btn).toJS()
    _btn.MenuName = config.MenuName + '-' + card.name + '-' + btn.label
    _btn.ParentMenuID = config.uuid
    this.props.history.push('/popdesign/' + window.btoa(window.encodeURIComponent((JSON.stringify(_btn)))))
    if (_btn.config) {
      _btn.config.uuid = _btn.uuid
      _btn.config.MenuID = _btn.uuid
      _btn.config.ParentId = card.uuid
      _btn.config.MenuName = _btn.label
    } else {
      _btn.config = {
        uuid: _btn.uuid,
        MenuID: _btn.uuid,
        ParentId: card.uuid,
        enabled: false,
        MenuName: _btn.label,
        tables: config.tables || [],
        Template: 'CustomPage',
        components: [],
        viewType: 'popview',
        style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
      }
    }
    this.setState({view: 'popview', popConfig: _btn})
  }
  closeView = () => {
@@ -391,7 +430,7 @@
        if (!config) {
          config = {
            version: 1.0,
            version: 2.0,
            uuid: MenuId,
            MenuID: MenuId,
            parentId: ParentId,
@@ -437,11 +476,20 @@
        config.open_edition = result.open_edition || ''
        window.GLOB.urlFields = config.urlFields || []
        this.setState({
          oriConfig: config,
          config: fromJS(config).toJS()
        })
        window.GLOB.customMenu = config
        if (config.version !== 2.0) {
          this.setState({
            oriConfig: fromJS(config).toJS(),
            comloading: true,
            needUpdate: true
          })
          this.updatePage(config)
        } else {
          this.setState({
            oriConfig: fromJS(config).toJS(),
            config: config
          })
          window.GLOB.customMenu = config
        }
      } else {
        notification.warning({
          top: 92,
@@ -452,8 +500,181 @@
    })
  }
  getMenuMessage = (delButtons, tbs) => {
    const { config } = this.state
  collectTB = (components, popBtns) => {
    return components.map(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          delete tab.floor
          delete tab.hasSearch
          delete tab.parentId
          tab.components = this.collectTB(tab.components, popBtns)
        })
      } else if (item.type === 'group') {
        item.components = this.collectTB(item.components, popBtns)
      } else {
        item.$tables = getTables(item, popBtns)
      }
      if (item.subtype === 'tablecard') { // 兼容
        item.type = 'card'
      }
      delete item.tabId
      delete item.parentId
      delete item.btnlog
      delete item.floor
      delete item.dataName
      return item
    })
  }
  setPopView = (components, parents, popbtns) => {
    return components.map(item => {
      if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          tab.components = this.setPopView(tab.components, parents, popbtns)
        })
      } else if (item.type === 'group') {
        item.components = this.setPopView(item.components, parents, popbtns)
      } else if (parents[item.uuid]) {
        this.setpopConfig(item, popbtns)
      }
      return item
    })
  }
  setpopConfig = (config, popbtns) => {
    config.subcards && config.subcards.forEach(item => {
      item.elements.forEach(cell => {
        if (cell.eleType !== 'button') return
        if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
          cell.config = popbtns[cell.uuid]
        }
      })
    })
    config.cols && config.cols.forEach(col => {
      if (col.type === 'action') {
        col.elements.forEach(cell => {
          if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
            cell.config = popbtns[cell.uuid]
          }
        })
      }
    })
    config.elements && config.elements.forEach(cell => {
      if (cell.eleType !== 'button') return
      if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
        cell.config = popbtns[cell.uuid]
      }
    })
    config.action && config.action.forEach(cell => {
      if (cell.OpenType === 'popview' && popbtns[cell.uuid]) {
        cell.config = popbtns[cell.uuid]
      }
    })
    config.$tables = getTables(config)
  }
  updatePage = (config) => {
    let popBtns = []
    config.components = this.collectTB(config.components, popBtns)
    config.version = 2.0
    if (popBtns.length === 0) {
      this.setState({
        config: config,
        comloading: false,
        needUpdate: true
      })
      return
    }
    Promise.all(popBtns.map((pop, i) => {
      return new Promise(resolve => {
        let param = {
          func: 'sPC_Get_LongParam',
          MenuID: pop.uuid
        }
        setTimeout(() => {
          Api.getSystemConfig(param).then(res => {
            let _config = null
            try {
              _config = res.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(res.LongParam))) : null
            } catch (e) {
              console.warn('Parse Failure')
              _config = null
            }
            if (_config && _config.Template !== 'CustomPage') {
              _config = null
            }
            if (_config) {
              _config.uuid = pop.uuid
              _config.MenuID = pop.uuid
              _config.ParentId = pop.parentId
              _config.MenuName = pop.label
              delete _config.MenuNo
              delete _config.open_edition
              delete _config.version
              _config.components = this.collectTB(_config.components)
            } else {
              _config = {
                uuid: pop.uuid,
                MenuID: pop.uuid,
                ParentId: pop.parentId,
                enabled: false,
                MenuName: pop.label,
                tables: config.tables || [],
                Template: 'CustomPage',
                components: [],
                viewType: 'popview',
                style: { backgroundColor: '#ffffff', backgroundImage: '', paddingTop: '16px', paddingBottom: '40px', paddingLeft: '16px', paddingRight: '16px' }
              }
            }
            resolve(_config)
          })
        }, i * 40)
      })
    })).then(results => {
      let bts = []
      results = results.map(res => {
        let tbs = []
        bts.push(...this.getMenuMessage(res, tbs))
        res.$tables = Array.from(new Set(tbs))
        return res
      })
      bts = bts.map(bt => bt.replace(/select\s'/, '').replace(/'\sas.*/, ''))
      bts.push(...popBtns.map(pop => pop.uuid))
      let parents = {}
      let popbtns = {}
      results.forEach(item => {
        parents[item.ParentId] = true
        popbtns[item.uuid] = item
      })
      config.components = this.setPopView(config.components, parents, popbtns)
      this.setState({ delButtons: bts, config, comloading: false })
    })
  }
  getMenuMessage = (config, tbs) => {
    let buttons = []
    let _sort = 1
@@ -462,89 +683,47 @@
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
        if (item.action && item.action.length > 0) {
          item.action.forEach(btn => {
            if (btn.hidden === 'true') return
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
            _sort++
          })
        }
        if (item.type === 'tabs') {
          item.subtabs.forEach(tab => {
            traversal(tab.components)
          })
        } else if (item.type === 'group') {
          traversal(item.components)
        } else if (item.type === 'card' || (item.type === 'table' && item.subtype === 'tablecard')) {
          item.action && item.action.forEach(btn => {
            if (btn.hidden === 'true') {
              delButtons.push(btn.uuid)
              return
            }
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'card' || item.type === 'carousel' || item.type === 'timeline') {
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.hidden === 'true') {
                delButtons.push(cell.uuid)
                return
              }
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              if (cell.hidden === 'true') return
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
              _sort++
            })
            card.backElements && card.backElements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.hidden === 'true') {
                delButtons.push(cell.uuid)
                return
              }
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              _sort++
            })
          })
        } else if (item.type === 'carousel' || item.type === 'timeline') {
          item.subcards.forEach(card => {
            card.elements && card.elements.forEach(cell => {
              if (cell.eleType !== 'button') return
              if (cell.hidden === 'true') {
                delButtons.push(cell.uuid)
                return
              }
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
              if (cell.hidden === 'true') return
              buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
              _sort++
            })
          })
        } else if (item.type === 'balcony') {
          item.elements && item.elements.forEach(cell => {
            if (cell.eleType !== 'button') return
            if (cell.hidden === 'true') {
              delButtons.push(cell.uuid)
              return
            }
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort`)
            if (cell.hidden === 'true') return
            buttons.push(`select '${cell.uuid}' as menuid, '${item.name + '-' + cell.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
            _sort++
          })
        } else if (item.type === 'line' || item.type === 'bar' || item.type === 'chart') {
          item.action && item.action.forEach(btn => {
            if (btn.hidden === 'true') {
              delButtons.push(btn.uuid)
              return
            }
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'table' && (item.subtype === 'normaltable' || item.subtype === 'editable')) {
          item.action && item.action.forEach(btn => {
            if (btn.hidden === 'true') {
              delButtons.push(btn.uuid)
              return
            }
            buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
            _sort++
          })
        } else if (item.type === 'table') {
          item.cols && item.cols.forEach(col => {
            if (col.type !== 'action') return
            col.elements.forEach(btn => {
              if (btn.hidden === 'true') {
                delButtons.push(btn.uuid)
                return
              }
              buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort`)
              if (btn.hidden === 'true') return
              buttons.push(`select '${btn.uuid}' as menuid, '${item.name + '-' + btn.label}' as menuname, '${_sort * 10}' as Sort, '${config.uuid}' as parentid, 40 as Type`)
              _sort++
            })
          })
@@ -554,31 +733,38 @@
    traversal(config.components)
    if (config.interfaces) {
      config.interfaces.forEach(item => {
        if (item.$tables) {
          tbs.push(...item.$tables)
        }
      })
    }
    return buttons
  }
  submitConfig = () => {
    const { MenuType, copyButtons } = this.state
    let config = fromJS(this.state.config).toJS()
  checkBase = () => {
    const { MenuType, config } = this.state
    if (MenuType === 'billPrint' && config.printPage === 'page' && !config.everyPCount) {
      return false
    } else if (MenuType === 'home' && (config.cacheUseful === 'true' && !config.cacheTime)) {
      return false
    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId || (config.cacheUseful === 'true' && !config.cacheTime))) {
      return false
    }
    return true
  }
  submitConfig = () => {
    const { MenuType } = this.state
    let config = fromJS(this.state.config).toJS()
    if (!this.checkBase()) {
      notification.warning({
        top: 92,
        message: '请完善基本信息!',
        duration: 5
      })
      return
    } else if (MenuType === 'home' && (config.cacheUseful === 'true' && !config.cacheTime)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
    } else if (MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId || (config.cacheUseful === 'true' && !config.cacheTime))) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
@@ -594,8 +780,7 @@
      }
      let tbs = []
      let delButtons = fromJS(this.state.delButtons).toJS()
      let btns = this.getMenuMessage(delButtons, tbs)
      let btns = this.getMenuMessage(config, tbs)
      let arr = []
      tbs = tbs.filter(tb => {
        let _tb = tb.toLowerCase()
@@ -654,24 +839,14 @@
        ParentID: config.uuid,
        MenuNo: config.MenuNo,
        Template: 'CustomPage',
        PageParam: '',
        LongParam: '',
        LText: []
        button_proc_edition: 'Y'
      }
      let btnIds = '' // 用于复制按钮的过滤
      if (MenuType !== 'billPrint') {
        btnParam.LText = btns
        btnParam.LText = btnParam.LText.join(' union all ')
      btnParam.LText = btns.join(' union all ')
        btnIds = btnParam.LText
        btnParam.LText = Utils.formatOptions(btnParam.LText)
        btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
        btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
      } else {
        btnParam.LText = ''
      }
      btnParam.LText = Utils.formatOptions(btnParam.LText)
      btnParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
      btnParam.secretkey = Utils.encrypt(btnParam.LText, btnParam.timestamp)
      new Promise(resolve => {
        if (MenuType === 'billPrint') { // 打印生成页面效果图
@@ -695,206 +870,86 @@
                  Remark: '',
                  temp_type: 'billprint',
                }).then(response => {
                  if (response.status) {
                    resolve(true)
                  } else {
                    notification.warning({
                      top: 92,
                      message: response.message,
                      duration: 5
                    })
                    resolve(false)
                  }
                  resolve(response)
                })
              } else {
                notification.warning({
                  top: 92,
                  message: result.ErrMesg,
                  duration: 5
                })
                resolve(false)
                resolve(result)
              }
            })
          })
        } else {
          resolve(true)
          resolve({status: true})
        }
      }).then(res => { // 按钮删除
        if (!res) return
      }).then(res => { // 页面保存
        if (!res || !res.status) return res
        if (delButtons.length === 0) {
        return Api.getSystemConfig(param)
      }).then(res => { // 按钮删除
        if (!res || !res.status) return res
        if (MenuType !== 'billPrint') { // 基本信息改变时,通知菜单列表更新
          localStorage.setItem('menuUpdate', new Date().getTime() + ',' + config.uuid)
        }
        config.open_edition = res.open_edition || ''
        this.setState({
          config,
          oriConfig: fromJS(config).toJS(),
          needUpdate: false
        })
        if (this.state.delButtons.length === 0) {
          return {
            status: true
          }
        } else {
          let _param = {
            func: 'sPC_MainMenu_Del',
            MenuID: delButtons.join(',')
            MenuID: this.state.delButtons.join(',')
          }
          return Api.getSystemConfig(_param)
        }
      }).then(res => { // 页面保存
        if (!res) return
        if (res.status) {
          return Api.getSystemConfig(param)
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
          return false
        }
      }).then(res => { // 页面按钮关系保存
        if (!res) return
        if (!res || !res.status) return res
        if (res.status) {
          if (MenuType !== 'billPrint') { // 基本信息改变时,通知菜单列表更新
            let ori = this.state.oriConfig
            if (config.MenuName !== ori.MenuName || config.MenuNo !== ori.MenuNo || config.parentId !== ori.parentId) {
              localStorage.setItem('menuUpdate', new Date().getTime())
            }
          }
          config.open_edition = res.open_edition || ''
          this.setState({
            config,
            oriConfig: fromJS(config).toJS(),
          })
        this.setState({
          delButtons: []
        })
          if (btnParam.LText) {
            return Api.getSystemConfig(btnParam)
          } else {
            return {
              status: true
            }
          }
        if (MenuType !== 'billPrint') {
          return Api.getSystemConfig(btnParam)
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
          return false
        }
      }).then(res => { // 按钮复制
        if (!res) return
        if (!res.status) {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
          return false
        }
        if (copyButtons.length === 0) {
          return {
            status: true
          }
        } else {
          return new Promise(resolve => {
            let deffers = copyButtons.map(item => {
              return new Promise(resolve => {
                if (btnIds.indexOf(item.uuid) === -1) { // 复制的按钮已删除
                  resolve({
                    status: true
                  })
                  return
                }
                Api.getSystemConfig({
                  func: 'sPC_Get_LongParam',
                  MenuID: item.$originUuid
                }).then(result => {
                  if (result.status) {
                    let _conf = ''
                    try {
                      _conf = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : ''
                    } catch (e) {
                      console.warn('Parse Failure')
                      _conf = ''
                    }
                    if (_conf) {
                      _conf.components = MenuUtils.resetConfig(_conf.components)
                      _conf.uuid = item.uuid
                      _conf.MenuID = item.uuid
                      _conf.Template = 'CustomPage'
                      _conf.enabled = false
                    } else {
                      resolve({
                        status: true
                      })
                      return
                    }
                    let _param = {
                      func: 'sPC_ButtonParam_AddUpt',
                      ParentID: config.uuid,
                      MenuID: item.uuid,
                      MenuNo: '',
                      Template: 'CustomPage',
                      MenuName: item.label,
                      PageParam: JSON.stringify({Template: 'CustomPage'}),
                      LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_conf)))
                    }
                    Api.getSystemConfig(_param).then(response => {
                      resolve(response)
                    })
                  }
                })
              })
            })
            Promise.all(deffers).then(result => {
              let error = null
              result.forEach(response => {
                if (!response.status) {
                  error = response
                }
              })
              if (error) {
                notification.warning({
                  top: 92,
                  message: error.message,
                  duration: 5
                })
                resolve(false)
              } else {
                resolve({
                  status: true
                })
              }
            })
          })
        }
      }).then(res => {
        if (res && res.status) {
          this.setState({
            delButtons: [],
            copyButtons: [],
            menuloading: false
          })
        this.setState({
          menuloading: false
        })
        if (!res) return
        if (res.status) {
          notification.success({
            top: 92,
            message: '保存成功',
            duration: 2
          })
          MKEmitter.emit('completeSave')
        } else {
          this.setState({
            menuloading: false
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
        MKEmitter.emit('completeSave')
      })
    }, 300 + (+sessionStorage.getItem('mkDelay')))
  }
  getRoleFields = () => {
    if (sessionStorage.getItem('sysRoles') || sessionStorage.getItem('permFuncField')) return
    if (sessionStorage.getItem('sysRoles')) return
    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
      if (res.status) {
        let _permFuncField = []
@@ -983,7 +1038,8 @@
        tree: '树形列表',
        chart: '自定义图表',
        editor: '富文本',
        group: '分组'
        group: '分组',
        iframe: 'iframe'
      }
      let subforbid = {
        editable: '可编辑表格',
@@ -1047,6 +1103,7 @@
  changeSetting = () => {
    this.setState({settingshow: !this.state.settingshow})
    sessionStorage.setItem('settingshow', '' + !this.state.settingshow)
    setTimeout(() => {
      MKEmitter.emit('tabsChange', 'all')
@@ -1054,19 +1111,19 @@
  }
  render () {
    const { activeKey, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, customComponents, eyeopen } = this.state
    const { view, comloading, MenuType, MenuId, config, settingshow, ParentId, menuloading, customComponents, eyeopen, needUpdate } = this.state
    return (
      <ConfigProvider locale={_locale}>
        <div className={'pc-menu-view ' + (MenuType || '')}>
          <Header />
          <DndProvider backend={HTML5Backend}>
        <Header />
        <DndProvider backend={HTML5Backend}>
          {view !== 'popview' ? <div className={'pc-menu-view ' + (MenuType || '')}>
            <div className="menu-body">
              <div className={'menu-setting ' + (!settingshow ? 'hidden' : '')}>
                <div className="draw">
                  {settingshow ? <DoubleLeftOutlined onClick={this.changeSetting}/> : <DoubleRightOutlined onClick={this.changeSetting}/>}
                </div>
                <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
                <Collapse accordion defaultActiveKey="basedata" bordered={false}>
                  {/* 基本信息 */}
                  <Panel header="基本信息" key="basedata">
                    {/* 菜单信息 */}
@@ -1121,19 +1178,19 @@
                    <StyleCombControlButton menu={config} />
                    <PasteController insert={this.insert} />
                    <Switch className="big" checkedChildren="启" unCheckedChildren="停" checked={config && config.enabled} onChange={this.onEnabledChange} />
                    <Button type="primary" id="save-config" onClick={this.submitConfig} loading={menuloading}>保存</Button>
                    <Button type="primary" id="save-config" className={needUpdate ? 'update-tip' : ''} onClick={this.submitConfig} loading={menuloading}>保存</Button>
                    <Button type="default" onClick={this.closeView}>关闭</Button>
                  </div>
                } style={{ width: '100%' }}>
                  {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
                  {config && !comloading ? <MenuShell menu={config} handleList={this.updateConfig} /> : <Spin className="loading-config" size="large" />}
                </Card>
              </div>
            </div>
          </DndProvider>
          <StyleController />
          <StyleCombController />
          <ModalController />
        </div>
          </div> : <PopView btn={this.state.popConfig} save={this.submitPopConfig} cancel={this.closePop}/>}
        </DndProvider>
        <ModalController />
        <StyleController />
        <StyleCombController />
      </ConfigProvider>
    )
  }