king
2025-05-13 1a176e4bdba485301385caac1a29102e598d25cc
src/views/billprint/index.jsx
@@ -1,7 +1,8 @@
import React, { Component } from 'react'
import { is, fromJS } from 'immutable'
import { Col, Row, Spin, notification, Button } from 'antd'
import { Col, Row, Spin, notification, Button, Modal } from 'antd'
import moment from 'moment'
import md5 from 'md5'
import Api from '@/api'
import Utils from '@/utils/utils.js'
@@ -44,8 +45,11 @@
    visible: false,
    rePos: false,
    loading: false,
    auto: true
    auto: true,
    ismob: /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent)
  }
  reloading = false
  UNSAFE_componentWillMount() {
    const { params } = this.props.match
@@ -62,10 +66,22 @@
        let param = JSON.parse(window.decodeURIComponent(window.atob(params.param)))
  
        sessionStorage.setItem('dataM', param.dataM || '')
        let urlParam = {...param}
        delete urlParam.tempId
        delete urlParam.pageId
        delete urlParam.dataM
        Object.keys(urlParam).forEach(key => {
          if (key === key.toLowerCase()) return
          urlParam[key.toLowerCase()] = urlParam[key]
          delete urlParam[key]
        })
        this.setState({
          BID: param.id || '',
          tempId: param.tempId,
          urlParam: param,
          urlParam: urlParam,
          pageId: param.pageId || ''
        }, () => {
          setTimeout(() => {
@@ -87,17 +103,29 @@
  }
  componentDidMount() {
    const _this = this
    const that = this
    if (window.GLOB.sysType !== 'cloud') {
      Object.defineProperty(window, 'debugger', {
        configurable: true,
        enumerable: true,
        set(value) {
          if (value + '' === 'false') {
            window.GLOB.debugger = false
          } else {
          if (value === true) {
            window.GLOB.debugger = true
          } else if (value === 0) {
            if (window.backend) {
              sessionStorage.setItem('systemRun', 'front')
              window.location.reload()
            } else {
              window.mkInfo('系统当前未使用后端脚本!')
            }
          } else if (value === false) {
            if (sessionStorage.getItem('systemRun') === 'front') {
              sessionStorage.removeItem('systemRun')
              window.location.reload()
            } else {
              window.GLOB.debugger = false
            }
          }
        }
      })
@@ -115,7 +143,7 @@
            window.GLOB.breakpoint = value + ''
            sessionStorage.setItem('breakpoint', value)
          }
          _this.debugChange()
          that.debugChange()
        }
      })
    }
@@ -141,7 +169,7 @@
        window.GLOB.breakpoint = false
        sessionStorage.removeItem('breakpoint')
        
        _this.debugChange()
        that.debugChange()
      }
    }
  }
@@ -166,13 +194,15 @@
        sessionStorage.setItem('LoginUID', result.LoginUID || '')
        sessionStorage.setItem('dataM', 'false')
        this.getMenuParam()
        // 获取系统信息
        let _param = {
          func: 's_Get_style',
          TypeCharOne: 'PC',
          LText: `select '${window.GLOB.appkey}'`,
        }
        if (window.GLOB.style_appkey) {
          _param.style_appkey = window.GLOB.style_appkey
        }
        _param.userid = result.UserID
@@ -184,6 +214,7 @@
          if (res.status) {
            window.GLOB.style = res.CSS
            document.title = res.titleName
            sessionStorage.setItem('appname', res.appname || '')
        
            if (window.GLOB.style && styles[window.GLOB.style]) {
              document.body.className = styles[window.GLOB.style] + ' ' + (res.split_line_show === 'false' ? 'hidden-split-line' : '')
@@ -197,6 +228,8 @@
              document.getElementsByTagName('head')[0].appendChild(link)
            }
          }
          this.getMenuParam()
        })
      } else {
        notification.warning({
@@ -250,6 +283,10 @@
          return
        }
        if (config.webTitle) {
          document.title = config.webTitle
        }
        config.style = config.style || {}
        config.pageSize = ['A4', 'A3', 'A5'].includes(config.pageSize) ? config.pageSize : 'A4'
        config.pageLayout = config.pageLayout !== 'horizontal' ? 'vertical' : 'horizontal'
@@ -295,6 +332,30 @@
        config.components = config.components.filter(item => !['tabs', 'search'].includes(item.type))
        let urlparam = urlParam ? {...urlParam} : {}
        if (config.urlFields && config.urlFields.length) {
          config.urlFields.forEach(field => {
            let key = field.toLowerCase()
            if (urlparam[key] !== undefined) return
            urlparam[key] = ''
          })
        }
        if (window.backend && config.allSqls) {
          let keys = Object.keys(urlparam)
          config.allSqls.forEach(item => {
            item.id = md5(window.GLOB.appkey + item.v_id)
            if (['datasource', 'interface', 'excelOut'].includes(item.type)) {
              item.urlkeys = keys
              item.urlparam = urlparam
              if (config.flow_code) {
                item.works_flow_code = config.flow_code
              }
            }
            window.GLOB.CacheData.set('sql_' + item.uuid, item)
          })
        }
        let userName = sessionStorage.getItem('User_Name') || ''
        let fullName = sessionStorage.getItem('Full_Name') || ''
@@ -312,7 +373,7 @@
        if (config.urlFields) {
          config.urlFields.forEach(field => {
            let val = `'${urlParam ? (urlParam[field] || '') : ''}'`
            let val = `'${urlparam[field.toLowerCase()]}'`
            regs.push({
              reg: new RegExp('@' + field + '@', 'ig'),
              value: val
@@ -324,7 +385,7 @@
        let initInters = []
        this.formatInterSetting(config.interfaces, regs, initInters, params, BID)
        this.formatInterSetting(config.interfaces, regs, initInters, params, BID, config.MenuName)
        config.components = config.components.map(component => {
          if (component.action) {
@@ -340,6 +401,8 @@
            component.$searches = []
          }
          component.data = [] // 初始化数据为空
          component.$menuname = (config.MenuName || '') + '-' + (component.name || '')
          if (component.subtype === 'tablecard') { // 兼容
            component.type = 'card'
@@ -358,7 +421,22 @@
          if (component.type === 'table') {
            let getColumns = (cols) => {
              return cols.filter(item => {
                if (item.type === 'colspan') {
                if (item.Hide === 'true') return false
                item.IsSort = 'false'
                if (item.type === 'number') {
                  if (typeof(item.decimal) === 'number') {
                    item.round = Math.pow(10, item.decimal)
                    if (item.format === 'percent') {
                      item.decimal = item.decimal > 2 ? item.decimal - 2 : 0
                    }
                  }
                } else if (item.type === 'formula') {
                  if (typeof(item.decimal) === 'number') {
                    item.round = Math.pow(10, item.decimal)
                  }
                } else if (item.type === 'colspan') {
                  item.subcols = getColumns(item.subcols)
                  if (item.subcols.length === 0) {
                    return false
@@ -380,6 +458,10 @@
                  }
                } else {
                  item.IsSort = 'false'
                }
                if (item.marks && item.marks.length === 0) {
                  item.marks = null
                }
          
                return true
@@ -447,11 +529,19 @@
          if (!component.format) return component  // 没有动态数据  数据格式 array 或 object
          component.setting.arr_field = component.columns ? component.columns.map(col => col.field).join(',') : ''
          component.setting.laypage = false   // 是否分页,转为boolean 统一格式
          component.setting.$name = component.$menuname
          if (component.format === 'object') {
            component.setting.$top = true
          }
          if (component.setting.interType !== 'system') { // 不使用系统函数时
            component.setting.sync = 'false'
            return component
          }
          component.setting.uuid = component.uuid
    
          let _customScript = ''
          let _tailScript = ''
@@ -470,7 +560,6 @@
          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) {
@@ -498,11 +587,17 @@
    
          component.setting.customScript = _customScript // 整理后自定义脚本
          component.setting.tailScript = _tailScript     // 后置自定义脚本
          if (window.backend && config.allSqls) {
            component.setting.sync = 'false'
          } else if (_tailScript) {
            component.setting.sync = 'false'
          }
          component.dataName = 'mk' + component.uuid.slice(-18)
    
          // floor    组件的层级
          // pageable 是否分页,组件属性,不分页的组件才可以统一查询
          if (component.setting.sync === 'true') {
            component.dataName = 'mk' + component.uuid.slice(-18)
            let param = this.getDefaultParam(component)
            _pars.push(param)
          } else if (component.subtype !== 'dualdatacard') {
@@ -517,11 +612,34 @@
          return component
        })
        _pars = this.getFormatParam(_pars)
        _pars = this.getFormatParam(_pars, config.MenuName)
        if (_pars) {
          _pars.componentId = 'union'
          _pars.componentId = ''
          params.unshift(_pars)
        } else if (window.backend && config.allSqls && params.length > 0) {
          let data = []
          let ids = []
          params = params.filter(item => {
            if (!item.$backend || item.public) return true
            ids.push(item.componentId)
            item.data[0].exps.forEach(cell => {
              if (cell.key === 'mk_obj_name') {
                cell.value = 'mk' + item.componentId.slice(-18)
              }
            })
            data.push(item.data[0])
            return false
          })
          if (data.length > 0) {
            params.push({
              $backend: true,
              $type: 's_Get_TableData',
              componentId: '',
              componentIds: ids,
              data
            })
          }
        }
        if (config.everyPCount && !config.printPage) { // 兼容
@@ -540,8 +658,20 @@
          auto: config.printPage === 'auto',
          config
        }, () => {
          if (config.normalcss) {
            let node = document.getElementById(config.uuid)
            node && node.remove()
            let ele = document.createElement('style')
            ele.id = config.uuid
            ele.innerHTML = config.normalcss
            document.getElementsByTagName('head')[0].appendChild(ele)
          }
          if (params.length === 0 && initInters.length === 0) {
            this.setState({loadingview: false, pages: [config.components]})
            this.autoExec()
          } else if (initInters.length > 0) {
            this.loadinit(initInters, params)
          } else {
@@ -586,6 +716,13 @@
    if (cell.style.display === 'inline-block') {
      cell.style.verticalAlign = 'top'
    }
    if (cell.marks && cell.marks.length === 0) {
      cell.marks = null
    }
    if (cell.anchors && cell.anchors.length === 0) {
      cell.anchors = null
    }
    
    if (['text', 'number', 'formula'].includes(cell.eleType)) {
      cell.innerHeight = cell.innerHeight || 'auto'
@@ -596,13 +733,15 @@
        if (cell.format === 'percent') {
          cell.decimal = cell.decimal > 2 ? cell.decimal - 2 : 0
        }
      } else if (cell.eleType === 'formula' && typeof(cell.decimal) === 'number') {
        cell.round = Math.pow(10, cell.decimal)
      }
    }
    return cell
  }
  formatInterSetting = (inters, regs, initInters, params, BID) => {
  formatInterSetting = (inters, regs, initInters, params, BID, MenuName) => {
    if (!inters) return []
    let delay = 15
@@ -614,6 +753,7 @@
      inter.setting.supModule = ''
      inter.setting.arr_field = inter.columns.map(col => col.field).join(',')
      inter.setting.$name = (MenuName || '') + '-公共数据源-' + inter.setting.name
      if (inter.setting.interType !== 'system') {
        let param = UtilsDM.getQueryDataParams(inter.setting, [], inter.setting.order || '', 1, 1000, BID)
@@ -628,6 +768,8 @@
        }
        return
      }
      inter.setting.uuid = inter.uuid
      let _customScript = ''
      let _tailScript = ''
@@ -645,9 +787,9 @@
      })
      delete inter.scripts
      inter.setting.$name = '公共数据源-' + inter.setting.name
      inter.setting.execute = inter.setting.execute !== 'false'
      inter.setting.laypage = true
      inter.setting.laypage = false
      inter.setting.$top = true
      if (!inter.setting.execute) {
        inter.setting.dataresource = ''
@@ -719,16 +861,11 @@
      _dataresource = `select top 1000 ${setting.arr_field} from ${_dataresource} `
    }
    // 测试系统打印查询语句
    if (window.GLOB.debugger === true) {
      _customScript &&  console.info(`${_dataresource ? '' : '/*不执行默认sql*/\n'}${_customScript}`)
      _dataresource &&  console.info(_dataresource)
    }
    return {
      name: dataName,
      columns: columns,
      par_tablename: '',
      order: setting.order || '',
      type: format === 'array' ? format : '',
      primaryKey: setting.primaryKey || '',
      foreign_key: '',
@@ -737,7 +874,7 @@
    }
  }
  getFormatParam = (params) => {
  getFormatParam = (params, MenuName) => {
    const { BID } = this.state
    if (!params || params.length === 0) return ''
@@ -755,6 +892,19 @@
    let district = sessionStorage.getItem('district') || ''
    let address = sessionStorage.getItem('address') || ''
    let regoptions = [
      { reg: /@pageSize@/ig, value: 9999 },
      { reg: /@pageIndex@/ig, value: 1},
      { reg: /@ID@/ig, value: `''`},
      { reg: /@BID@/ig, value: `'${BID || ''}'`},
      { reg: /@LoginUID@/ig, value: `'${sessionStorage.getItem('LoginUID') || ''}'`},
      { reg: /@SessionUid@/ig, value: `'${localStorage.getItem('SessionUid') || ''}'`},
      { reg: /@UserID@/ig, value: `'${sessionStorage.getItem('UserID') || ''}'`},
      { reg: /@Appkey@/ig, value: `'${window.GLOB.appkey || ''}'`},
      { reg: /@lang@/ig, value: `'${sessionStorage.getItem('lang')}'`},
      { reg: /@typename@/ig, value: `'admin'`},
    ]
    let LText = params.map((item, index) => {
      let _sql = item.sql
      let _script = item.script
@@ -766,6 +916,20 @@
        `
      }
      _sql = _sql.replace(/@orderBy@/ig, item.order)
      _script = _script.replace(/@orderBy@/ig, item.order)
      regoptions.forEach(cell => {
        _sql = _sql.replace(cell.reg, cell.value)
        _script = _script.replace(cell.reg, cell.value)
      })
      // 测试系统打印查询语句
      if (window.GLOB.debugger === true) {
        _script && window.mkInfo(`${_sql ? '' : '/*不执行默认sql*/\n'}${_script}`)
        _sql && window.mkInfo(_sql)
      }
      item.columns.forEach(cell => {
        LText_field.push(`Select '${item.name}' as tablename,'${cell.field}' as fieldname,'${cell.datatype}' as field_type`)
      })
@@ -774,17 +938,21 @@
    let param = {
      func: 'sPC_Get_structured_data',
      LText: LText.join(' union all '),
      LText_field: LText_field.join(' union all '),
      BID: BID || '',
      username: userName,
      fullName: fullName
    }
    param.LText = Utils.formatOptions(param.LText)
    param.LText_field = Utils.formatOptions(param.LText_field)
    if (MenuName) {
      param.menuname = MenuName
    }
    param.exec_type = window.GLOB.execType || 'y'
    param.LText = Utils.formatOptions(LText.join(' union all '), param.exec_type)
    param.custom_script = Utils.formatOptions(LText_field.join(' union all '), param.exec_type)
    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    param.secretkey = Utils.encrypt('', param.timestamp)
    return param
  }
@@ -796,11 +964,13 @@
      return new Promise(resolve => {
        Api.genericInterface(item).then(res => {
          if (!res.status) {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            if (res.ErrCode !== '-2') {
              notification.warning({
                top: 92,
                message: res.message,
                duration: 5
              })
            }
            resolve()
          } else {
            let _data = { $$empty: true }
@@ -817,6 +987,8 @@
    Promise.all(deffers).then(() => {
      if (params.length === 0) {
        this.setState({loadingview: false, pages: [this.state.config.components]})
        this.autoExec()
      } else {
        this.loadmaindata(params)
      }
@@ -831,28 +1003,49 @@
    let deffers = params.map(item => {
      let componentId = item.componentId
      let ispublic = item.public
      let ids = item.componentIds
      delete item.componentId
      delete item.componentIds
      delete item.public
      return new Promise(resolve => {
        Api.genericInterface(item).then(res => {
          if (!res.status) {
            notification.warning({
              top: 92,
              message: res.message,
              duration: 5
            })
            if (item.func === 'sPC_Get_structured_data' && /将截断字符串或二进制数据/ig.test(res.message)) {
              res.message = res.message + '请检查字段集'
            }
            if (res.ErrCode === 'version_up') {
              this.reloadTabs()
            } else if (res.ErrCode !== '-2') {
              notification.warning({
                top: 92,
                message: res.message,
                duration: 5
              })
            }
            resolve(false)
          } else if (ids) {
            ids.forEach(id => {
              let _id = 'mk' + id.slice(-18)
              if (res[_id]) {
                let _data = { $$empty: true }
                if (res[_id][0]) {
                  _data = res[_id][0]
                }
                window.GLOB.CacheData.set(id, _data)
              }
            })
            resolve(res)
          } else {
            res.componentId = componentId
            if (ispublic) {
              let _data = { $$empty: true }
              if (res.data && res.data[0]) {
                _data = res.data[0]
              }
              window.GLOB.CacheData.set(componentId, _data)
            let _data = { $$empty: true }
            if (res.data && res.data[0]) {
              _data = res.data[0]
            }
            window.GLOB.CacheData.set(componentId, _data)
            resolve(res)
          }
        })
@@ -875,7 +1068,7 @@
        _results.forEach(res => {
          if ((res.componentId === item.uuid || res.componentId === item.componentId) && res.data) {
            item.dataArray = fromJS(res.data).toJS()
          } else if (res.componentId === 'union' && res[item.dataName]) {
          } else if (res[item.dataName]) {
            let data = res[item.dataName]
            if (!Array.isArray(data)) {
              data = [data]
@@ -907,63 +1100,79 @@
        }
      }
      while (!over) {
        let page = []
        let count = 0
        let _pageover = false
        comps.forEach(comp => {
          let item = fromJS(comp).toJS()
          if (item.wrap.printType === 'headerOrfooter') { // 页眉页脚
            item.data = item.dataArray || null
            setData(item)
            page.push(item)
            comp.added = true
          }
          if (_pageover) return
          if (item.$page && comp.dataArray.length > 0) {
            item.data = []
            while (count + 1 <= limit && comp.dataArray.length > 0) {
              item.data.push(comp.dataArray.shift())
              count++
            }
            if (count >= limit || comp.dataArray.length > 0) {
              _pageover = true
            }
            if (comp.dataArray.length === 0) {
      if (this.state.config.printPage === 'custom' && this.state.config.printScripts) {
        try {
          // eslint-disable-next-line
          let func = new Function('components', 'pages', 'notification', this.state.config.printScripts)
          func(comps, pages, notification)
        } catch (e) {
          console.warn(e)
          notification.warning({
            top: 92,
            message: '自定义脚本执行错误!',
            duration: 5
          })
        }
      } else {
        while (!over) {
          let page = []
          let count = 0
          let _pageover = false
          comps.forEach(comp => {
            let item = fromJS(comp).toJS()
            if (item.wrap.printType === 'headerOrfooter') { // 页眉页脚
              item.data = item.dataArray || null
              setData(item)
              page.push(item)
              comp.added = true
            }
            setData(item)
            page.push(item)
          } else if (!comp.added) {
            if (item.wrap.printHeight) {
              count += item.wrap.printHeight
              if (count >= limit) {
                _pageover = true
                return
            if (_pageover) return
            if (item.$page && comp.dataArray.length > 0) {
              item.data = []
              while (count + 1 <= limit && comp.dataArray.length > 0) {
                item.data.push(comp.dataArray.shift())
                count++
              }
              if (count >= limit || comp.dataArray.length > 0) {
                _pageover = true
              }
              if (comp.dataArray.length === 0) {
                comp.added = true
              }
              setData(item)
              page.push(item)
            } else if (!comp.added) {
              if (item.wrap.printHeight) {
                count += item.wrap.printHeight
                if (count >= limit) {
                  _pageover = true
                  return
                }
              }
              item.data = item.dataArray || null
              setData(item)
              page.push(item)
              comp.added = true
            }
            item.data = item.dataArray || null
            setData(item)
            page.push(item)
            comp.added = true
          })
          pages.push(page)
          pageIndex++
          if (pageIndex >= 2000 || comps.findIndex(comp => !comp.added) === -1) {
            over = true
          }
        })
        pages.push(page)
        pageIndex++
        if (pageIndex >= 2000 || comps.findIndex(comp => !comp.added) === -1) {
          over = true
        }
      }
@@ -998,6 +1207,40 @@
      })
      this.setState({loadingview: false, pages, rePos})
      this.autoExec()
    })
  }
  autoExec = () => {
    const { config } = this.state
    if (config.autoExec !== 'true') return
    setTimeout(() => {
      this.print()
    }, config.autoExecSplit || 500)
  }
  reloadTabs = () => {
    if (this.reloading) return
    let time = new Date().getTime()
    let oldTime = sessionStorage.getItem('mk_reloadTabs')
    if (oldTime && time - oldTime < 180000) return
    sessionStorage.setItem('mk_reloadTabs', time)
    this.reloading = true
    Api.getAppVersion(true).then(() => {
      window.location.reload()
    }, (message) => {
      Modal.error({
        title: message || '系统配置更新失败!',
      })
    })
  }
@@ -1252,7 +1495,7 @@
  }
  render() {
    const { loadingview, viewlost, config, pages, auto, rePos, loading } = this.state
    const { loadingview, viewlost, config, pages, auto, rePos, loading, ismob } = this.state
    return (
      <div className="bill-print-wrap" >
@@ -1262,8 +1505,8 @@
        </div> : null}
        {viewlost ? <NotFount msg={this.state.lostmsg} /> : null}
        {config && window.GLOB.breakpoint ? <DebugTable /> : 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}
        {pages && !loadingview && !viewlost && !ismob ? <div className="print-button"><Button icon="printer" size="large" shape="circle" onClick={this.print}></Button></div> : null}
        {!loadingview && !viewlost && !ismob ? <div className="refresh-button"><Button icon="reload" size="large" shape="circle" onClick={this.reload}></Button></div> : null}
      </div>
    )
  }