Vue前端实现预览并打印PDF文档

一. 需求

  1. 点击文档列表中的【打印】按钮,获取后台生成的PDF的url,弹窗进行预览:

2. 点击【打印】按钮,进行打印预览和打印:

二. 需求实现

首先后台给的是word文档,研究了一圈后发现暂时无法实现(需要跳转谷歌预览、格式错乱等问题),于是要求后台大佬给换成pdf。

非常感谢大佬dearmrzhang的分享,这篇文章实现的需求比本文复杂的多,我这里只是单页pdf的预览和打印,大佬的分享则涉及img和pdf的分别处理、分页等,原文:手摸手系列之前端Vue实现PDF预览及打印的终极解决方案

我的代码比较简单,注意首先需要在项目引入这两个库:

vue-pdf

print-js

1. 模版
复制代码
<template>
  <div class="main">
    <div style="padding: 20px">
      <a-form layout="inline" style="color: black; margin-bottom: 22px">
        <a-row :gutter="48">
          <a-col>
            <a-form-item label="运单号" style="margin-right: 30px">
              <a-input placeholder="请输入运单号" allow-clear size="large" v-model="queryParam.waybillNo"></a-input>
            </a-form-item>
            <sava-button class="button" @click="doSearch">查询</sava-button>
          </a-col>
        </a-row>
      </a-form>
      <a-table
        ref="table"
        :columns="columns"
        :dataSource="loadData"
        :loading="loading"
        :row-key="(record) => record.id"
        :pagination="pagination"
        @change="handleTableChange"
        style="margin-top: 10px"
      >
        <span slot="action" slot-scope="text, record">
          <!-- <a @click="handleEdit(record)" style="color: #2b79c2">编辑</a> -->
          <a @click="viewDetail(record)" style="color: #2b79c2; margin-left: 10px">查看</a>
          <a @click="printBill(record)" style="color: #2b79c2; margin-left: 10px">打印</a>
        </span>
      </a-table>

      <a-modal :visible="previewVisibleForAll" :footer="null" @cancel="handleCancelAll" :width="800">
        <div style="overflow-y: auto; overflow-x: hidden">
          <a-button shape="round" icon="file-pdf" @click="handlePrint(printData)" size="small">打印</a-button>
          <div id="printFrom">
            <pdf ref="pdf" :src="previewFileSrc"></pdf>
          </div>
        </div>
      </a-modal>
    </div>
  </div>
</template>
2. 核心业务逻辑
复制代码
<script>
// 两个库引入
import pdf from 'vue-pdf'
import printJS from 'print-js'
// 接口
import { reqWayBillList, reqBillReport } from '@/api/DigitalWayBill/DigitalWayBill'

export default {
  components: {
    pdf,
  },
  data() {
    return {
      queryParam: {
        waybillNo: '',
      },
      columns: [
      ],
      loadData: [],
      loading: false,
      pagination: {},
      mdl: null,
      enterpriseInfo: [],
      inspectorInfo: [],
      fenceParam: {},
      pdfUrl: '', // 你的 PDF 文件 URL
      progress: 0,
      printData: {
        printable: 'printFrom',
        header: '',
        ignore: ['no-print'],
      },
      previewVisibleForAll: false,
      pageTotal: null,
      previewFileSrc: '',
    }
  },
  created() {
    this.doSearch()
  },

  methods: {
    doSearch() {
      this.loading = true
      reqWayBillList(this.queryParam).then((res) => {
        console.log('way bill list', res)
        this.loadData = res.records
        this.loading = false
      })
    },
    handleTableChange(pagination) {
      const pager = { ...this.pagination1 }
      pager.current = pagination.current
      this.pagination1 = pager
      this.queryParam1.pageIndex = pagination.current
      this.doSearch()
    },

    viewDetail(record) {
      console.log('click view')
      this.mdl = { ...record }
      // 将获取的信息传递到新页面
      this.$router.push({
        path: '/bill/detail',
        query: {
          data: JSON.stringify(this.mdl),
        },
      })
    },
    printBill(record) {
      this.$message.success('生成文档需要一些时间, 请稍候...', 10)
      reqBillReport(record.waybillNo)
        .then((res) => {
          console.log('pdf url', res)
          this.previewFileSrc = res
          this.previewVisibleForAll = true
        })
        .catch((err) => {
          this.$message.error(`获取文档失败: ${err}`)
        })
    },
    handlePrint(params) {
      printJS({
        printable: params.printable, // 'printFrom', // 标签元素id
        type: params.type || 'html',
        header: params.header, // '表单',
        targetStyles: ['*'],
        style: '@page {margin:0 10mm};', // 可选-打印时去掉眉页眉尾
        ignoreElements: params.ignore || [], // ['no-print']
        properties: params.properties || null,
      })
    },
    printPdf() {
      this.$refs.pdf.print()
      // window.print()
    },
    handleCancel() {
      this.previewVisible = false
    },
    handleCancelAll() {
      this.previewVisibleForAll = false
    },
  },
}
</script>
3. 样式

没有额外的样式,都写在模版标签里了

三. 总结

市面上有一些pdf预览和打印的库,正如dearmrzhang大佬讲的,都有一些不足;通过与print-js的组合使用,才完美解决了预览和打印的需求。

感谢观看,希望本文能帮助您解决相关需求问题。

相关推荐
怕浪猫5 小时前
FDE 如何正确解决现场项目工程性的问题
前端·后端·ai编程
西瓜太郎12346 小时前
外层模型卡片与分组详情成功率不一致,应该怎么排查?
前端·typescript·go·软件工程·react
GreenTea6 小时前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
毕业设计7039 小时前
(免费领源码) 基于微信小程序的预制菜商城的设计与实现25172-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·python·mysql·微信小程序·pycharm·微信开发者工具·推荐算法
xifangge20259 小时前
AGENTS.md 怎么写?涵盖 Java、Python、Vue、Go 的 8 套开箱即用模板
java·vue.js·python
几何心凉9 小时前
没有万能模型:我用 AiiOnly Token Plan,把多款大模型的长处拼进同一个项目
前端
kyriewen9 小时前
Claude Code 的额度今天缩水了17%——官方公告上写的是"永久提高25%"
前端·ai编程·claude
雪芽蓝域zzs10 小时前
vue解构平铺VS对象包裹
前端·javascript·vue.js
风骏时光牛马10 小时前
从零到实战,完整AI学习路线
前端
三十而立洋11 小时前
深入理解 Monorepo:子包安装依赖
前端·前端工程化