vue中实现打印通过iframe标签

需求:1、实现(横向/纵向)打印 ,考虑打印边距

2、打印某一列内容超过一定长度,隐藏并且字体变小

遇到的问题:1、打印页面中无法使用 class 样式

2、最好使用 table ,不要使用 element(样式错乱)

3、内容超出如何隐藏

完成实例图:

横向布局
vue中实现打印通过iframe标签_第1张图片
纵向布局
vue中实现打印通过iframe标签_第2张图片

1、完成需要打印页面,先布局

<template>
	<div id="printTemplate" style="display: none">
    <div style="page-break-after:always" v-for="(item,index) in printData" :key="index">
      <div class="header" style="margin: 20px 0 0 0">
        <div style="text-align: right;">页号:第{{index + 1}}/{{printData.length}}页div>
        <div style="text-align: center;position: relative;margin-bottom: 10px">
          <div class="header-title" style="font-size: 25px;font-weight: bold">日记账div>
        div>
        <div style="margin-bottom:14px;">
          <div>账户:{{pringPageInformation.accountName}}div>
        div>
        <div style="display: flex;justify-content: space-between;margin-bottom: 18px;">
          <div>币别:{{pringPageInformation.currencyName}}div>
          <div>期间/日期:{{pringPageInformation.periodTime}}div>
        div>
      div>
      <div class="content">
        <table border="2" cellspacing="0" cellpadding="0" width="100%">
          <thead>
            <tr style="height:30px;">
              <th style="height:30px;width:130px">日期th>
              <th style="height:30px;width:207px">摘要th>
              <th style="height:30px;width:124px">收入金额th>
              <th style="height:30px;width:124px">支出金额th>
              <th style="height:30px;width:149px">余额th>
            tr>
          thead>
          <tbody style="page-break-after: always;padding: 30px;">
            <tr v-for="(value,zIndex) in item" :key="zIndex" style="height:30px;">
              <td :style="value.selfStyle">{{value.createTime}}td>
              // 这里需要注意,超过当前表格高度对 td 使用overflow:hidden;
              //里边嵌套一层div,要不然会显示省略号
              <td :style="value.selfStyle">
                <div style="height:30px">很长的文字很长的文字很长的文字很长的文字很长的文字很长的文字很长的文字很长的文字很长的文字div>
              td>
              <td :style="value.selfStyle">100.00td>
              <td :style="value.selfStyle">200.00td>
              <td :style="value.selfStyle">300.00td>
            tr>
          tbody>
        table>
      div>
      <div class="footer">
        <div style="display:flex;"><p style="width:70px;">核算单位p><p>核算单位p>div>
        <div style="display:flex;"><p style="width:70px;">制单p><p>制单p>div>
      div>
    div>
  div>
template>

<script>
export default {
	name: 'print-template-voucher',
	props: {
		printData: {
			type: Array,
			default() {
				return []
			}
		},
		pringPageInformation: {
			type: Object,
			default() {
				return {}
			}
		}

	},
	data() {
		return {
		
		}
	},
}
script>

<style lang="stylus" rel="stylesheet/stylus">style>

2、打印效果需要生成二位数组

/**
 * @description: 打印模版,每页固定打印的条数
 * @param {Array} data 总共的数据
 * @param {number} pageSize 每页分页的条数,默认20条
 * @return {Array} 分页后的二维数组
 */
export function printPageDataFn(data, pageSize = 20){
    const printTable = []
    if (data && data.length > 0) {
        let remainderLength = Math.floor(data.length / pageSize) * pageSize,
        pagedata = [],
        pageNum = 0
        for (let i = 0; i < data.length; i ++) {
            if (pageNum < pageSize) {
                pagedata.push(data[i])
            }
            pageNum ++
            if (pageNum === pageSize || (i > remainderLength && i === data.length - 1)) {
                printTable.push(pagedata)
                pagedata = []
                pageNum = 0
            }
        }
        if (pageSize > data.length && pagedata && pagedata.length > 0) {
            printTable.push(pagedata)
        }
    }
    return printTable
}

3、处理内容超过一定长度,隐藏并且字体变小,创建一个标签,将内容插入,并计算宽度即可

4、iframe 实现打印

/**
 * @description:  打印模板
 * @param {sting} domId 当前打印模版的 id
 * @param {boolean} noMargin 是否去除边距
 * @param {sting} direction 打印方向 landscape;//横向 portrait;//纵向
 * @param {sting} margin 自定义打印边距
 */
export function printTemplateByDomId(domId, noMargin, direction = '', margin = 0) {
	let ele = document.getElementsByTagName('iframe')

	let iframe = null

	if (!ele.length) {
		iframe = document.createElement('IFRAME')
		document.body.appendChild(iframe)
	} else {
		iframe = ele[0]
	}
	iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;')
	let doc = iframe.contentWindow.document

	doc.write(document.getElementById(domId).innerHTML)
	doc.close()

	//去除边距
	if (noMargin) {
		let parent = doc.getElementsByTagName('html')[0]

		let styleEle = doc.createElement('style')
		if (direction) {
			styleEle.innerHTML = `@page { margin: 0; padding: 0;size: ${direction}}`
		} else {
			styleEle.innerHTML = '@page { margin: 0; padding: 0;}'
		}
		parent.appendChild(styleEle)
	} else {
		let parent = doc.getElementsByTagName('html')[0]

		let styleEle = doc.createElement('style')
		if (direction) {
			styleEle.innerHTML = `@page { margin: ${margin}; padding: 0;size: ${direction}}`
		} else {
			styleEle.innerHTML = `@page { margin: ${margin}; padding: 0;}`
		}
		parent.appendChild(styleEle)
	}

	iframe.contentWindow.focus()
	iframe.contentWindow.print()
}

你可能感兴趣的:(javascript,vue,vue.js,javascript,前端)