Vue项目打印总结

此处是vue项目中的用法,也可以改写,不使用vue的语法,也可以实现其他框架使用

window.print()

直接调用默认打印,设置打印时样式

@media print {
  @page {
    margin: 0.5cm;
  }
}

普通打印

打印分页表格时,可以实现各分页分别都展示表头。有高度限制,超出了就不展示表头(各浏览器不同)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>打印测试</title>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    table {
      font-size: 12px;
      width: 100%;
      font-size: 9pt;
      border-collapse: collapse;
      border-spacing: 0;
    }

    tr {
      page-break-inside: avoid;
    }

    td {
      border: 1px solid #ccc;
      text-align: center;
      height: 36px;
    }
  </style>
</head>

<body>
  <div id="demo">
    <table>
      <thead style="display:table-header-group;font-weight:bold">
        <tr>
          <td colspan="2" align="center" style="font-weight:bold;border:3px double red">每页都有的表头</td>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item,index) in list">
          <td>{{item.a+index}}</td>
          <td>{{item.b+index}}</td>
        </tr>
      </tbody>
      <tfoot style="display:table-footer-group;font-weight:bold">
        <tr>
          <td colspan="2" align="center" style="font-weight:bold;border:3px double blue">每页都有的表尾</td>
        </tr>
      </tfoot>
    </table>
  </div>
  <script>
    const DEMO = {
      data() {
        return {
          list: []
        }
      },
      mounted() {
        this.list = new Array(50).fill({ a: 1, b: 10 })
        this.$nextTick(() => {
          window.print()
        })
      },
      methods: {

      }
    }

    Vue.createApp(DEMO).mount('#demo')
  </script>
</body>

</html>

根据表头自动计算打印分页

实现功能:动态表头,计算打印数据
注意:

  1. 在使用方法时,需要在打印时,将打印纸的宽高确定,在样式表设置打印的width,height

this. u D e e p C l o n e 深克隆方法 t h i s . uDeepClone 深克隆方法 this. uDeepClone深克隆方法this.pluc cm、px转换方法

/**
 * 实现打印表头分页
 * 前提:表格结构
 * index 为外层循环的index
 * A4纸打印 21cm*29.7cm
 *
 * <table>
 * <thead :ref="'thead' + index"></thead>
 * <tbody :ref="'tbody' + index">
 *  <tr :ref="'tr' + index"></tr> //分割的数组
 * </tbody>
 * </table>
 *
 * @param {Array} parentData 打印数据
 * @param {String}  name  切分循环的数据
 */
export default {
  methods: {
    // 重写打印页面 根据改变打印数据 printData.tableList 实现
    calcPrintRender(parentData, name) {
      let footH = 30 //最后一行高度
      let pageH = this.$pluc.cm2px(29.7) - footH // 计算px
      let newPrintData = this.$uDeepClone(parentData) //重写数据
      newPrintData = newPrintData.map((v, i) => {
        v.symbol = i //添加标识位
        v.paging = '1/1'
        return v
      })
      for (let pI in parentData) {
        let item = parentData[pI]
        let detailArr = item[name]

        let thead = this.$refs[`thead${pI}`][0]
        let tbody = this.$refs[`tbody${pI}`][0]
        let tr = this.$refs[`tr${pI}`]
        if (thead && tbody && tr) {
          let theadH = thead.offsetHeight //头部高度
          let renderBody = pageH - theadH
          if (theadH > pageH) {
            continue
          }
          let tbodyH = tbody.offsetHeight
          console.log('pageH, theadH, tbodyH,renderBody', pageH, theadH, tbodyH, renderBody)
          // tr总高度
          let trTotal = tr.reduce((prev, next) => {
            console.log(next.offsetHeight)
            return prev + next.offsetHeight
          }, 0)
          // console.log(' trTotal', trTotal)
          if (theadH + tbodyH < pageH) {
            // 不做处理
            continue
          }
          // 获取渲染函数
          let sliceArr = this.deepRenderTr({ tr, renderBody, trTotal })
          // console.log('sliceArr', sliceArr)
          for (let newI in newPrintData) {
            let newItem = newPrintData[newI]
            if (newItem.symbol == pI) {
              let len = sliceArr.length
              if (len > 0) {
                let newArr = []
                sliceArr.forEach((v, i) => {
                  let obj = this.$uDeepClone(item)
                  if (i == 0) {
                    obj[name] = detailArr.slice(0, v)
                  } else {
                    obj[name] = detailArr.slice(sliceArr[i - 1], v)
                  }
                  obj.paging = `${i + 1}/${len + 1}`
                  newArr.push(obj)
                })
                // 推送最后一组数据
                let nObj = this.$uDeepClone(item)
                let last = sliceArr[len - 1] - detailArr.length
                nObj[name] = detailArr.slice(last)
                nObj.paging = `${len + 1}/${len + 1}`
                newArr.push(nObj)
                newPrintData.splice(newI, 1, ...newArr)
              }
            }
          }
        }
      }
      // console.log('new', newPrintData)
      return newPrintData
    },
    // 获取哪些tr需要截取
    deepRenderTr({ arr = [], tr, renderBody, trTotal }) {
      // 找到第一页 最后 tr的index 暂不考虑表头占满情况
      // console.log(arr, tr.length, renderBody, trTotal)
      let trSum = 0
      let firstPageIndex = null
      for (let trI in tr) {
        trSum += tr[trI].offsetHeight
        if (trSum >= renderBody) {
          firstPageIndex = trI - 1
          break
        }
      }
      if (firstPageIndex === null) {
        return arr
      } else {
        // 计算剩余高度
        let restH = trTotal - trSum + tr[firstPageIndex + 1].offsetHeight
        if (arr.length > 0) {
          let n = firstPageIndex + arr[arr.length - 1]
          arr.push(n)
        } else {
          arr.push(firstPageIndex)
        }
        if (restH < renderBody) {
          return arr
        } else {
          let newTr = tr.slice(firstPageIndex + 1, tr.length)
          let param = { arr: arr, tr: newTr, renderBody: renderBody, trTotal: restH }
          return this.deepRenderTr(param)
        }
      }
    },
  },
}

cm与px的转换

var ratio = 0
pluc()
export default {
  px2cm: function(px) {
    return Math.floor((px * 10) / ratio) / 10
  },
  px2mn: function(px) {
    var r = ratio / 10
    return Math.floor(px / r)
  },
  cm2px: function(cm) {
    return Math.floor(cm * ratio)
  },
  mm2px: function(mm) {
    var r = ratio / 10
    return Math.floor(mm * r)
  },
}

function pluc() {
  'use strict'
  var div = document.createElement('div')
  div.style.width = '1cm'
  div.id = 'puc'
  document.body.appendChild(div)
  var w = getComputedStyle(div, null).width
  ratio = w.substr(0, w.length - 2)
  div.parentNode.removeChild(div)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值