vue 如何实现表格打印功能

概述:常见的打印有JavaScript打印、jQuery、vue打印,这里主要讲述vue使用vue-print-nb进行打印,废话不多说,直接手摸手上代码!

实际效果图展示:

数据结构:

安装依赖

npm install vue-print-nb --save

页面引用

import print from 'vue-print-nb'

父组件DOM

xml 复制代码
<div class="table-manage-20">
  <!-- 标题栏 -->
  <llsTitleBox title="打印功能" :back="false">
    <template slot="button">
      <llsButton type="primary" @click="batchPrintHandle">打印</llsButton>
      
      // directives自定义print事件,目的:
         1. 取代将print在man.js全局注入(Vue.use(Print))
         2. 当点击打印按钮后,会将打印列表printObj对象进行赋值,此时就会打开打印列表组件,取代将打印列表组件进行传统的显示影藏操作
      <llsButton type="primary" ref="printBtn" v-show="false" v-print="printObj"></llsButton>
    </template>
  </llsTitleBox>
  <!-- 表格 -->
  <div style="padding:0 15px;">
    <lls-table :max-height="tableHeight" :data="tableList" @selection-change="handleSelectionChange">
    <lls-table-column type="selection" width="55"></lls-table-column>
    <lls-table-column type="index" label="序号" width="50"></lls-table-column>
    <lls-table-column prop="assetNo" min-width="180" label="编号"></lls-table-column>
    <lls-table-column prop="assetId" min-width="180" label="数字证编号"></lls-table-column>
    <lls-table-column prop="coreCompanyName" min-width="200" label="企业"></lls-table-column>
    <lls-table-column prop="amount" min-width="150" :formatter="formatMoney" align="right" label="金额(元)"></lls-table-column>
    <lls-table-column prop="operateTime" label="操作"  width="60" fixed="right">
      <template v-slot:default="{ row }">
         <div class="table-btn" @click="printHandle([row])">打印</div>
      </template>
    </lls-table-column>
  </lls-table>
  // 打印列表组件
  <div class="hide">
     // 打印区域组件上需要加id="printContent",与打印组件绑定
     <div id="printContent">
       // page-break-after:always:设置在表格元素之后始终进行分页的分页行为:在元素后插入分页符,原因:当一页表格内容放不下的情况不会进行分页,内容会被截断,此样式可以解决该问题
       // printList:为当前全选或单选的对象,该数据将会填充打印表格的结构数据
       <printTemplate style="page-break-after:always" v-for="(item, index) in printList" :baseData="item" :key="index"></printTemplate>
     </div>
   </div>

父组件js代码

xml 复制代码
<script>
  import print from 'vue-print-nb'
  import printTemplate from './printTemplate.vue'
  export default {
    components: {
      printTemplate
    },
    // 自定义print指令,页面中v-print使用,触发打印插件
    directives: {
      print   
    },
    data() {
        return {
            tableHeight: "400px",
            tableList: [], //表格数据对象
            multipleSelection: [],
            printList: [],
            // 打印对象
            printObj: {
            id: "printContent",
          }
        };
    },
    mounted() {
        this.$nextTick(() => {
            // 整个视图高度
            let screenHeight = document.body.offsetHeight;
            // 查询组件DOM,视项目情况而定(搜索组件高度)
            let searchBarHeight = this.$refs.searchBar.clientHeight;
            let dataContent = screenHeight - 44 * 2 - searchBarHeight - 50;
            this.tableHeight = `${dataContent}px`;
        });
    },
    methods: {
        // 全选单选事件
        handleSelectionChange(val) {
          this.multipleSelection = val;
        },
        // 打印按钮
        batchPrintHandle() {
          if(!this.multipleSelection.length) {
            return this.$message.error("请先选择数据!");
          } else {
            this.printHandle(this.multipleSelection)
          }
        },
        printHandle(printList) {
            // 将数据重新拷贝解构赋值,打印列表数据
            this.printList = [...printList]
            this.$nextTick(() => {
                // 获取打印按钮DOM结构
                const btnEl = this.$refs.printBtn.$el
                // 对打印按钮自定义click事件
                const clickEvent = new MouseEvent('click')
                // dispatchEvent原生触发自定义click事件,打开打印组件
                btnEl.dispatchEvent(clickEvent)
            })
        },

父组件样式代码

css 复制代码
.hide {
  width: 0; height: 0; overflow: hidden;
}

printTemplate子组件DOM

xml 复制代码
<template>
  <div class="print-wrapper">
    <div class="print-title">打印表单</div>
    <div class="print-table-wrapper">
        <table border="1" cellspacing="0" cellpadding="0"  class="print-table">
        <tr>
          <td colspan="4">基本信息:</td>
        </tr>
        <tr>
          <td class="label">客户名称</td>
          <td colspan="3">{{baseData.sedCompanyName}}</td>
        </tr>
        <tr>
          <td class="label">企业名称</td>
          <td colspan="3">{{baseData.coreCompanyName}}</td>
        </tr>
        <tr>
          <td class="label">金额(元)</td>
          <td >{{baseData.realAmount | formatMoney}}</td>
          <td class="label">期限(天)</td>
          <td>{{baseData.loanTerm }}</td>
        </tr>
        <tr>
        <td class="label">费率(%)</td>
          <td colspan="3">{{baseData.interestRate}}</td>
        </tr>
        <tr>
          <td class="label">应收款(元)</td>
          <td colspan="3">{{baseData.amount | formatMoney}}</td>
        </tr>
        <tr>
          <td class="label">编号</td>
          <td colspan="3">{{baseData.assetId}}</td>
        </tr>
        <tr>
          <td class="label">客户收款银行</td>
          <td colspan="3">{{baseData.toBankName}}</td>
        </tr>
        <tr>
          <td class="label">客户收款账户名</td>
          <td colspan="3">{{baseData.toName}}</td>
        </tr>
        <tr>
          <td class="label">客户收款账号</td>
          <td colspan="3">{{baseData.toAccount}}</td>
        </tr>
        <tr>
            <td class="label">卡号</td>
          <td colspan="3">{{baseData.unitedBankNumber}}</td>
        </tr>
        <tr>
          <td colspan="4" class="label">处理意见:</td>
        </tr>
        <tr v-for="(item, index) in baseData.approveLogs" :key="index">
          <td class="label">{{item.name | sliceSuffix}}</td>
          <td colspan="3">{{item.approveResultName}}&nbsp;&nbsp; {{item.approveTime}}&nbsp;&nbsp; {{item.assignee}}&nbsp;&nbsp; {{item.approvalOpinions}}</td>
        </tr>
      </table>
    </div>
  </div>
</template>

printTemplate子组件 js

javascript 复制代码
export default {
  name: 'printTemplate',
  props: {
    baseData: {
      type: Object,
      default: () => {}
    }
  },
  // js过滤器方法
  filters: {
    // 上面本是负责人审批,由于项目需求,需要将审批字段去掉,自己项目视情况而定
    sliceSuffix(name) {
      // endsWith() 是一种字符串方法,用于确定字符串是否以特定的字符序列结尾。返回一个布尔值
      return name.endsWith('审批') ? name.slice(0, -2) : name
    },
    
    // 金额格式化,格式化效果见顶端需求实现图
    formatMoney(value) {
      value = Number(value).toFixed(2);
      const index = value.indexOf('.');
      if (index != -1) {
          var decimalPart = value.substring(0, index);
          var pointPart = value.substring(index + 1);
          decimalPart = decimalPart.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');    // 整数部分做格式化
          value = decimalPart + "." + pointPart;
      } else {
          value = value.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
      }
      return value
    }
  },

3.printTemplate子组件样式

xml 复制代码
<style lang="scss" scoped>
// 解决el-table表格内容过多,打印不全问题
@page {
  size: auto;
  margin: 3mm;
}
.print-wrapper {
  padding:0 20px;
  .print-title {
    text-align: center;
    font-size: 20px;
    line-height: 40px;
    font-weight: bold;
    margin-bottom: 20px;
    
  }
  .print-table-wrapper {
    border: 1px solid #000;
    padding: 3px;
    margin-bottom: 20px;
    .print-table {
      width: calc(100% - 3px);
      border-collapse: collapse;
      border: 3px solid #000;
      td {
        height: 40px;
        padding: 0 10px;
        border: 1px solid #333;
        color: #333;
        &.label {
          width: 180px;
        }
      }
    }
  }
}
</style>

注意事项:

该打印列表为表格数据打印,如果为其他需求打印,该方法将不再适用,请参考指令 v-print="print",print的配置对象参数:
javascript 复制代码
print: {
    id: 'printArea',
    popTitle: '打印', // 打印配置页上方标题
    extraHead: '', //最上方的头部文字,附加在head标签上的额外标签,使用逗号分隔
    preview: '', // 是否启动预览模式,默认是false(开启预览模式,可以先预览后打印)
    previewTitle: '', // 打印预览的标题(开启预览模式后出现),
    previewPrintBtnLabel: '', // 打印预览的标题的下方按钮文本,点击可进入打印(开启预览模式后出现)
    zIndex: '', // 预览的窗口的z-index,默认是 20002(此值要高一些,这涉及到预览模式是否显示在最上面)   
    previewBeforeOpenCallback() {}, //预览窗口打开之前的callback(开启预览模式调用)
    previewOpenCallback() {}, // 预览窗口打开之后的callback(开启预览模式调用)
    beforeOpenCallback() {}, // 开启打印前的回调事件
    openCallback() {}, // 调用打印之后的回调事件
    closeCallback() {}, //关闭打印的回调事件(无法确定点击的是确认还是取消)
    url: '',
    standard: '',
    extraCss: '',
    },

END...

相关推荐
xjt_09011 分钟前
浅析Web存储系统
前端
foxhuli22939 分钟前
禁止ifrmare标签上的文件,实现自动下载功能,并且隐藏工具栏
前端
青皮桔1 小时前
CSS实现百分比水柱图
前端·css
失落的多巴胺1 小时前
使用deepseek制作“喝什么奶茶”随机抽签小网页
javascript·css·css3·html5
DataGear1 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
影子信息1 小时前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月1 小时前
1.vue权衡的艺术
前端·vue.js·开源
RunsenLIu1 小时前
基于Vue.js + Node.js + MySQL实现的图书销售管理系统
vue.js·mysql·node.js
样子20181 小时前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿1 小时前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js