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...

相关推荐
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.3 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl5 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫7 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友7 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻9 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js