king
2021-05-08 6afdec0062dacbded57e166230eb22cc55ced0c1
src/views/billprint/index.jsx
@@ -1,36 +1,37 @@
import React, { Component } from 'react'
import { DndProvider } from 'react-dnd'
import { is, fromJS } from 'immutable'
import HTML5Backend from 'react-dnd-html5-backend'
import { ConfigProvider, notification, Collapse, Card, Switch, Button } from 'antd'
import { Col, Row, Spin, notification, Button } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/mob.js'
import enUS from '@/locales/en-US/mob.js'
import antdEnUS from 'antd/es/locale/en_US'
import antdZhCN from 'antd/es/locale/zh_CN'
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import options from '@/store/options.js'
import UtilsDM from '@/utils/utils-datamanage.js'
import NotFount from '@/components/404'
import asyncComponent from '@/utils/asyncComponent'
import './index.scss'
const { Panel } = Collapse
const _locale = localStorage.getItem('lang') !== 'en-US' ? antdZhCN : antdEnUS
const Header = asyncComponent(() => import('@/menu/header'))
const MenuForm = asyncComponent(() => import('@/menu/menuform'))
const SourceWrap = asyncComponent(() => import('@/menu/modelsource'))
const MenuShell = asyncComponent(() => import('@/menu/menushell'))
const BgController = asyncComponent(() => import('@/menu/bgcontroller'))
const PaddingController = asyncComponent(() => import('@/menu/padcontroller'))
const StyleController = asyncComponent(() => import('@/menu/stylecontroller'))
const ModalController = asyncComponent(() => import('@/menu/modalconfig/controller'))
const TableComponent = asyncComponent(() => import('@/templates/sharecomponent/tablecomponent'))
// 通用组件
const AntvBarAndLine = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-bar-line'))
const AntvPie = asyncComponent(() => import('@/tabviews/custom/components/chart/antv-pie'))
const DataCard = asyncComponent(() => import('@/tabviews/custom/components/card/data-card'))
const PropCard = asyncComponent(() => import('@/tabviews/custom/components/card/prop-card'))
const TableCard = asyncComponent(() => import('@/tabviews/custom/components/card/table-card'))
const NormalTable = asyncComponent(() => import('@/tabviews/custom/components/table/normal-table'))
const BraftEditor = asyncComponent(() => import('@/tabviews/custom/components/editor/braft-editor'))
const SandBox = asyncComponent(() => import('@/tabviews/custom/components/code/sand-box'))
class BillPrint extends Component {
  state = {
    dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    loadingview: true,
    printing: false,
    pages: null,
    BID: '',
    data: '',
    tempId: '',
    config: null,
  }
@@ -39,9 +40,11 @@
    try {
      let param = JSON.parse(window.decodeURIComponent(window.atob(this.props.match.params.param)))
      sessionStorage.setItem('dataM', param.dataM || '')
      sessionStorage.setItem('localDataM', param.dataM || '')
      this.setState({
        BID: param.id,
        tempId: param.tempId,
        BID: param.id || '',
        tempId: param.tempId
      }, () => {
        this.getMenuParam()
      })
@@ -67,30 +70,182 @@
    }
  }
  getMenuParam = () => {
    const { tempId } = this.state
    const { tempId, BID } = this.state
    let param = {
      func: 's_PrintTemplateMGetData',
      Type: 'Y',
      PrintTempNO: tempId
    let _param = {
      func: 'sPC_Get_LongParam',
      MenuID: tempId
    }
    if (window.GLOB.mainSystemApi) { // 从单点登录服务器取打印配置信息
      param.rduri = window.GLOB.mainSystemApi
      _param.rduri = window.GLOB.mainSystemApi
    }
    Api.getLocalConfig(param).then(result => {
    Api.getLocalConfig(_param).then(result => {
      if (result.status) {
        // let config = null
        let config = ''
        // try {
        //   config = JSON.parse(window.decodeURIComponent(window.atob(result.ConfigParam)))
        // } catch (e) {
        //   console.warn('Parse Failure')
        //   config = null
        // }
        try {
          config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
        } catch (e) {
          console.warn('Parse Failure')
          config = ''
        }
        // 页面配置解析错误时提示
        if (!config) {
          this.setState({
            viewlost: true,
            loadingview: false
          })
          return
        }
        // 页面未启用时,显示未启用页面
        if (!config.enabled) {
          this.setState({
            viewlost: true,
            loadingview: false,
            lostmsg: this.state.dict['main.view.unenabled']
          })
          return
        }
        config.style = config.style || {}
        config.pageSize = ['A4', 'A3', 'A5'].includes(config.pageSize) ? config.pageSize : 'A4'
        config.pageLayout = config.pageLayout !== 'horizontal' ? 'vertical' : 'horizontal'
        config.pagePadding = config.pagePadding !== 'without' ? 'default' : 'without'
        let pageParam = {
          A4: {
            vertical: 980,
            horizontal: 1200,
            verticaldefault: 1.455,
            verticalwithout: 1.411,
            horizontaldefault: 0.679,
            horizontalwithout: 0.701,
          },
          A3: {
            vertical: 1200,
            horizontal: 1600,
            verticaldefault: 1.441,
            verticalwithout: 1.410,
            horizontaldefault: 0.688,
            horizontalwithout: 0.703,
          },
          A5: {
            vertical: 700,
            horizontal: 1000,
            verticaldefault: 1.478,
            verticalwithout: 1.413,
            horizontaldefault: 0.669,
            horizontalwithout: 0.700,
          }
        }
        config.width = pageParam[config.pageSize][config.pageLayout]
        config.style.height = Math.floor(config.width * pageParam[config.pageSize][config.pageLayout + config.pagePadding])
        if (config.printCustom === 'true' && config.printWidth && config.printHeight) {
          config.width = config.printWidth
          config.style.height = config.printHeight
        }
        let params = []
        let _pars = []
        config.components = config.components.filter(item => !['tabs', 'search'].includes(item.type))
        config.components = config.components.map(component => {
          if (component.action) component.action = []
          if (component.search) component.search = []
          component.data = [] // 初始化数据为空
          if (['propcard', 'brafteditor', 'sandbox'].includes(component.subtype) && component.wrap.datatype === 'static') {
            component.format = ''
          }
          if (!component.setting) return component // 不使用系统函数时
          if (!component.format) return component  // 没有动态数据  数据格式 array 或 object
          if (component.setting.interType !== 'system') { // 不使用系统函数时
            component.setting.sync = 'false'
            return component
          }
          let _customScript = ''
          component.scripts && component.scripts.forEach(script => {
            if (script.status !== 'false') {
              _customScript += `
              ${script.sql}
              `
            }
          })
          delete component.scripts
          component.setting.execute = component.setting.execute !== 'false'  // 默认sql是否执行,转为boolean 统一格式
          component.setting.laypage = false   // 是否分页,转为boolean 统一格式
          component.setting.onload = 'true'   // 默认加载
          if (!component.setting.execute) {
            component.setting.dataresource = ''
          }
          if (/\s/.test(component.setting.dataresource)) {
            component.setting.dataresource = '(' + component.setting.dataresource + ') tb'
          }
          if (sessionStorage.getItem('dataM') === 'true') { // 数据权限
            component.setting.dataresource = component.setting.dataresource.replace(/\$@/ig, '/*')
            component.setting.dataresource = component.setting.dataresource.replace(/@\$/ig, '*/')
            _customScript = _customScript.replace(/\$@/ig, '/*')
            _customScript = _customScript.replace(/@\$/ig, '*/')
          } else {
            component.setting.dataresource = component.setting.dataresource.replace(/@\$|\$@/ig, '')
            _customScript = _customScript.replace(/@\$|\$@/ig, '')
          }
          // 外联数据库替换
          if (window.GLOB.externalDatabase !== null) {
            component.setting.dataresource = component.setting.dataresource.replace(/@db@/ig, window.GLOB.externalDatabase)
            _customScript = _customScript.replace(/@db@/ig, window.GLOB.externalDatabase)
          }
          component.setting.customScript = _customScript // 整理后自定义脚本
          // floor    组件的层级
          // dataName 系统生成的数据源名称
          // pageable 是否分页,组件属性,不分页的组件才可以统一查询
          if (component.dataName && component.setting.sync === 'true') {
            let param = this.getDefaultParam(component)
            _pars.push(param)
          } else {
            let arr_field = component.columns.map(col => col.field).join(',')
            let param = UtilsDM.getQueryDataParams(component.setting, arr_field, [], component.setting.order || '', 1, 1000, BID, '')
            param.componentId = component.uuid
            params.push(param)
          }
          component.setting.sync = 'true'
          return component
        })
        _pars = this.getFormatParam(_pars)
        if (_pars) {
          _pars.componentId = 'union'
          params.unshift(_pars)
        }
        this.setState({
          config
        }, () => {
          if (params.length === 0) {
            this.setState({loadingview: false, pages: [config.components]})
          } else {
            this.loadmaindata(params)
          }
        })
      } else {
        notification.warning({
          top: 92,
@@ -99,245 +254,367 @@
        })
      }
    })
    // Api.getSystemConfig(param).then(result => {
    //   if (result.status) {
    //     let config = null
    //     try {
    //       config = JSON.parse(window.decodeURIComponent(window.atob(result.LongParam)))
    //     } catch (e) {
    //       console.warn('Parse Failure')
    //       config = null
    //     }
    //     if (!config) {
    //       config = {
    //         version: 1.0,
    //         uuid: MenuId,
    //         MenuID: MenuId,
    //         parentId: ParentId,
    //         Template: 'CustomPage',
    //         MenuType: MenuType,
    //         easyCode: '',
    //         enabled: false,
    //         MenuName: MenuName,
    //         MenuNo: MenuNo,
    //         tables: [],
    //         components: [],
    //         style: {
    //           backgroundColor: '#ffffff', backgroundImage: '',
    //           paddingTop: '16px', paddingBottom: '80px', paddingLeft: '16px', paddingRight: '16px'
    //         }
    //       }
    //     } else {
    //       config.uuid = MenuId
    //       config.MenuID = MenuId
    //       config.MenuType = config.MenuType || MenuType
    //     }
    //     if (MenuType === 'billPrint') {
    //       config.FstID = 'BillPrintTemp'
    //       config.SndID = 'BillPrintTemp'
    //       config.ParentID = 'BillPrintTemp'
    //     }
    //     this.setState({
    //       oriConfig: config,
    //       config: fromJS(config).toJS(),
    //       openEdition: result.open_edition || '',
    //     })
    //     this.getRoleFields()
    //   } else {
    //     notification.warning({
    //       top: 92,
    //       message: result.message,
    //       duration: 5
    //     })
    //   }
    // })
  }
  getRoleFields = () => {
    Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => {
      if (res.status) {
        let _permFuncField = []
        let _sysRoles = []
        if (res.Roles && res.Roles.length > 0) {
          _sysRoles = res.Roles.map(role => {
            return {
              uuid: Utils.getuuid(),
              value: role.RoleID,
              text: role.RoleName
            }
          })
        }
        if (res.sModular && res.sModular.length > 0) {
          res.sModular.forEach(field => {
            if (field.ModularNo) {
              _permFuncField.push(field.ModularNo)
            }
          })
          _permFuncField = _permFuncField.sort()
        }
        let config = {...this.state.config, sysRoles: _sysRoles, permFuncField: _permFuncField}
        this.setState({config})
      }
    })
  }
  initMenuList = (msg) => {
    let config = {...this.state.config, ...msg}
    this.setState({config})
  }
  onEnabledChange = () => {
    const { config } = this.state
    if (!config.enabled && this.verifyConfig(true)) {
      return
    }
  reload = () => {
    this.setState({
      config: {...config, enabled: !config.enabled}
    })
  }
  verifyConfig = (show) => {
    const { config } = this.state
    let error = ''
    if (!config.MenuID) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
    } else if (config.MenuType === 'custom' && (!config.MenuName || !config.MenuNo || !config.fstMenuId || !config.parentId)) {
      notification.warning({
        top: 92,
        message: '请完善菜单基本信息!',
        duration: 5
      })
      return
    }
    config.components.forEach(item => {
      if (error) return
      if (item.subtype === 'propcard' && item.wrap.datatype === 'static') return
      if (item.setting) {
        if (item.setting.interType === 'system' && item.setting.execute !== 'false' && !item.setting.dataresource) {
          error = `组件《${item.name}》未设置数据源!`
        } else if (item.setting.interType === 'system' && item.setting.execute === 'false' && item.scripts.length === 0) {
          error = `组件《${item.name}》未设置数据源!`
        } else if (item.setting.interType && !item.setting.primaryKey) {
          error = `组件《${item.name}》未设置主键!`
        }
      }
      if (item.type === 'bar' || item.type === 'line' || item.type === 'pie') {
        if (!item.plot.Xaxis) {
          error = `组件《${item.name}》图表字段尚未设置!`
        }
      }
    })
    if (show && error) {
      notification.warning({
        top: 92,
        message: error,
        duration: 5
      })
    }
    return error
  }
  // 更新配置信息
  updateConfig = (config) => {
    this.setState({
      config: config
      loadingview: true,
      pages: null,
      data: '',
      config: null
    }, () => {
      this.getMenuParam()
    })
  }
  /**
   * @description 更新常用表信息,快捷添加后更新配置信息
   * @description 获取系统存储过程 sPC_Get_TableData 的参数
   */
  updatetable = (config, fields) => {
    const { tableFields } = this.state
  getDefaultParam = (component) => {
    const { columns, setting, dataName, format } = component
    let arr_field = columns.map(col => col.field)
    let _dataresource = setting.dataresource
    let _customScript = setting.customScript
    config.tableFields = fields ? fields : tableFields
    if (setting.order && _dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from (select ${arr_field.join(',')} ,ROW_NUMBER() over(order by ${setting.order}) as rows from ${_dataresource}) tmptable order by tmptable.rows `
    } else if (_dataresource) {
      _dataresource = `select top 1000 ${arr_field.join(',')} from ${_dataresource} `
    }
    this.setState({
      tableFields: fields ? fields : tableFields,
      config
    // 测试系统打印查询语句
    if ((options.sysType === 'local' && !window.GLOB.systemType) || window.debugger === true) {
      _customScript &&  console.info(`${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      _dataresource &&  console.info(_dataresource)
    }
    return {
      name: dataName,
      columns: columns,
      par_tablename: '',
      type: format === 'array' ? format : '',
      primaryKey: setting.primaryKey || '',
      foreign_key: '',
      sql: _dataresource,
      script: _customScript
    }
  }
  getFormatParam = (params) => {
    const { BID } = this.state
    if (!params || params.length === 0) return ''
    let LText_field = []
    let LText = params.map((item, index) => {
      let _sql = item.sql
      let _script = item.script
      if (index === 0) {
        _script = `declare @ErrorCode nvarchar(50),@retmsg nvarchar(4000) select @ErrorCode='',@retmsg =''
          ${_script}
        `
      }
      item.columns.forEach(cell => {
        LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
      })
      return `Select '${item.name}' as tablename,'${window.btoa(window.encodeURIComponent(_sql))}' as LText,'${window.btoa(window.encodeURIComponent(_script))}' as Lcustomize,'${item.type}' as table_type,'${item.primaryKey}' as primary_key,'${item.par_tablename}' as par_tablename,'${item.foreign_key}' as foreign_key,'${index}' as Sort`
    })
    let param = {
      func: 'sPC_Get_structured_data',
      LText: LText.join(' union all '),
      LText_field: LText_field.join(' union all '),
      BID: BID || ''
    }
    param.LText = Utils.formatOptions(param.LText)
    param.LText_field = Utils.formatOptions(param.LText_field)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    return param
  }
  /**
   * @description 主表数据加载
   */
  loadmaindata = (params) => {
    const { components, everyPCount, firstCount, lastCount } = this.state.config
    let deffers = params.map(item => {
      let componentId = item.componentId
      delete item.componentId
      return new Promise(resolve => {
        Api.getLocalConfig(item).then(res => {
          if (!res.status) {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            resolve(false)
          } else {
            res.componentId = componentId
            resolve(res)
          }
        })
      })
    })
    Promise.all(deffers).then(results => {
      let _results = results.filter(Boolean)
      let comps = components.map(item => {
        if (!item.format) return item
        _results.forEach(res => {
          if (res.componentId === item.uuid && res.data) {
            item.data = res.data
            item.dataArray = fromJS(res.data).toJS()
          } else if (res.componentId === 'union' && res[item.dataName]) {
            item.data = res[item.dataName]
            item.dataArray = fromJS(res[item.dataName]).toJS()
          }
        })
        return item
      })
      let length = comps.length
      let pageIndex = 1
      let pages = []
      let over = false
      if (length === 0) {
        this.setState({loadingview: false, pages})
      }
      while (!over) {
        let page = []
        let count = 0
        let _pageover = false
        let pagesover = false
        let limit = pageIndex === 1 ? (firstCount || 20) : (everyPCount || 20)
        comps.forEach((_item, index) => {
          let item = fromJS(_item).toJS()
          if (index + 1 >= length && !_pageover) {
            pagesover = true
          }
          if (item.wrap && item.wrap.printType === 'headerOrfooter') { // 页眉页脚
            page.push(item)
          } else if (_pageover) {
            return
          } else if (item.subtype === 'datacard' || item.type === 'table') {
            if (_item.dataArray && _item.dataArray.length > 0) {
              item.data = []
              while (count < limit && _item.dataArray.length > 0) {
                item.data.push(_item.dataArray.shift())
                count++
              }
              if (count >= limit) {
                _pageover = true
              }
              page.push(item)
            }
          } else if (!item.added) {
            _item.added = true
            page.push(item)
          }
          if (index + 1 >= length && !_pageover) {
            pagesover = true
          }
        })
        if (pagesover && lastCount && count > lastCount) {
          pagesover = false
          page = []
          count = 0
          _pageover = false
          if (pageIndex === 1) {
            limit = (everyPCount - firstCount) + (everyPCount - lastCount)
            if (limit <= 0) {
              limit = firstCount
            }
          } else {
            limit = lastCount
          }
          comps.forEach((_item, index) => {
            let item = fromJS(_item).toJS()
            if (item.wrap && item.wrap.printType === 'headerOrfooter') { // 页眉页脚
              page.push(item)
            } else if (_pageover) {
              return
            } else if (item.subtype === 'datacard' || item.type === 'table') {
              if (_item.dataArray && _item.dataArray.length > 0) {
                item.data = []
                while (count < limit && _item.dataArray.length > 0) {
                  item.data.push(_item.dataArray.shift())
                  count++
                }
                if (count >= limit) {
                  _pageover = true
                }
                page.push(item)
              }
            } else if (!item.added) {
              _item.added = true
              page.push(item)
            }
            if (index + 1 === length && !_pageover) {
              pagesover = true
            }
          })
        }
        pages.push(page)
        pageIndex++
        if (pageIndex >= 200 || pagesover) {
          over = true
        }
      }
      this.setState({loadingview: false, pages})
    })
  }
  render () {
    const { activeKey, MenuType, dict, MenuId, config, ParentId, MenuName, MenuNo, menuloading } = this.state
  print = () => {
    const { config, printing } = this.state
    if (printing) return
    let jubuData = document.getElementById('bill-print').innerHTML
    this.setState({printing: true})
    try {
      let iframe = document.createElement('IFRAME')
      let linkList = document.getElementsByTagName('link')     // 获取父窗口link标签对象列表
      let styleList = document.getElementsByTagName('style')   // 获取父窗口style标签对象列表
      iframe.style.marginTop = '600px'
      document.body.appendChild(iframe)
      let doc = iframe.contentWindow.document
      doc.open()
      doc.write(`<!DOCTYPE html><html lang="en"><head>`)
      for (let i = 0;i < linkList.length;i++) {
        if (linkList[i].type === 'text/css') {
          doc.write(`<LINK rel="stylesheet" type="text/css" href="${linkList[i].href}">`)
        }
      }
      doc.write(`<style>body{width: ${config.width}px!important;}*{border-style: solid;border-width: 0;}</style>`)
      for (let i = 0;i < styleList.length;i++) {
        doc.write('<style>' + styleList[i].innerHTML + '</style>')
      }
      doc.write(`</head><body>`)
      doc.write(jubuData)
      doc.write(`</body></html>`)
      doc.close()
      setTimeout(() => {
        iframe.contentWindow.focus()
        iframe.contentWindow.print()
        document.body.removeChild(iframe)
        setTimeout(() => {
          window.close()
        }, 2000)
      }, 500)
    } catch (e) {
      notification.warning({
        top: 92,
        message: '打印异常!',
        duration: 5
      })
    }
  }
  getComponents = (components) => {
    return components.map(item => {
      if (item.type === 'bar' || item.type === 'line') {
        return (
          <Col span={item.width} key={item.uuid}>
            <AntvBarAndLine config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'pie') {
        return (
          <Col span={item.width} key={item.uuid}>
            <AntvPie config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'card' && item.subtype === 'datacard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <DataCard config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'card' && item.subtype === 'propcard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <PropCard config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'table' && item.subtype === 'tablecard') {
        return (
          <Col span={item.width} key={item.uuid}>
            <TableCard config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'table' && item.subtype === 'normaltable') {
        return (
          <Col span={item.width} key={item.uuid}>
            <NormalTable config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'editor') {
        return (
          <Col span={item.width} key={item.uuid}>
            <BraftEditor config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else if (item.type === 'code') {
        return (
          <Col span={item.width} key={item.uuid}>
            <SandBox config={item} initdata={item.data} mainSearch={[]} menuType="" />
          </Col>
        )
      } else {
        return null
      }
    })
  }
  render() {
    const { loadingview, viewlost, config, pages } = this.state
    return (
      <ConfigProvider locale={_locale}>
        <div className="pc-menu-view" id="view">
          <Header view="design" closeView={this.closeView} />
          <DndProvider backend={HTML5Backend}>
            <div className="menu-body">
              <div className="menu-setting">
                <Collapse accordion activeKey={activeKey} bordered={false} onChange={(key) => this.setState({activeKey: key})}>
                  {/* 基本信息 */}
                  <Panel header={dict['mob.basemsg']} key="basedata">
                    {/* 菜单信息 */}
                    {config && MenuType === 'custom' ? <MenuForm
                      dict={dict}
                      config={config}
                      MenuId={MenuId}
                      parentId={ParentId}
                      MenuName={MenuName}
                      MenuNo={MenuNo}
                      initMenuList={this.initMenuList}
                      updateConfig={this.updateConfig}
                    /> : null}
                    {/* 表名添加 */}
                    {config ? <TableComponent config={config} updatetable={this.updatetable}/> : null}
                  </Panel>
                  {/* 组件添加 */}
                  <Panel header={dict['mob.component']} key="component">
                    <SourceWrap MenuType={MenuType} />
                  </Panel>
                  <Panel header={'背景'} key="background">
                    {config ? <BgController config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
                  <Panel header={'内边距'} key="padding">
                    {config ? <PaddingController config={config} updateConfig={this.updateConfig} /> : null}
                  </Panel>
                </Collapse>
              </div>
              <div className={'menu-view ' + (menuloading ? 'saving' : '')}>
                <Card title={
                  <div> {config && config.MenuName} </div>
                } bordered={false} extra={
                  <div>
                    {config ? <Switch className="big" checkedChildren={dict['mob.enable']} unCheckedChildren={dict['mob.disable']} checked={config.enabled} onChange={this.onEnabledChange} /> : null}
                    <Button type="primary" onClick={this.submitConfig} loading={menuloading}>{dict['mob.save']}</Button>
                  </div>
                } style={{ width: '100%' }}>
                  {config && config.components ? <MenuShell menu={config} handleList={this.updateConfig} /> : null}
                </Card>
              </div>
            </div>
          </DndProvider>
          <StyleController />
          <ModalController />
        </div>
      </ConfigProvider>
      <div className="bill-print-wrap" >
        {loadingview && <Spin size="large" />}
        {pages ? <div id="bill-print">
          {pages.map((components, index) => (<div className="print-page" key={index} style={{...config.style, overflow: 'hidden', boxSizing: 'border-box'}}><Row>{this.getComponents(components)}</Row></div>))}
        </div> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
        {pages && !loadingview && !viewlost ? <div className="print-button"><Button icon="printer" size="large" shape="circle" onClick={this.print}></Button></div> : null}
        {!loadingview && !viewlost ? <div className="refresh-button"><Button icon="reload" size="large" shape="circle" onClick={this.reload}></Button></div> : null}
      </div>
    )
  }
}