pdfViewExample.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <template>
  2. <div class="pdf-view-example j-contanter">
  3. <div id="pdf-view-container" class="j-main" />
  4. <div v-if="!getUserId" class="j-footer">
  5. <a href="/jyapp/free/login?url=/jy_mobile/order/create/creditreport&activity=bidCreditReportPreview" class="adsense-container">
  6. <AdSingle
  7. ad="app-credit-report-sample"
  8. :show-tag="false"
  9. :show-close-icon="false"
  10. class="adsense-container"
  11. />
  12. </a>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. import { mapGetters } from 'vuex'
  18. import * as pdfjsLib from 'pdfjs-dist/build/pdf'
  19. import AdSingle from '@/components/ad/Ad'
  20. import { getAssetsFile } from '@/utils'
  21. import 'pdfjs-dist/build/pdf.worker.mjs'
  22. export default {
  23. name: 'PdfViewExample',
  24. components: {
  25. AdSingle
  26. },
  27. data() {
  28. return {
  29. pdfUrl: '',
  30. pdf: null,
  31. totalPages: 0,
  32. currentPage: 1, // 新增
  33. batchSize: 5 // 新增
  34. }
  35. },
  36. computed: {
  37. ...mapGetters('user', ['getUserId'])
  38. },
  39. created() {
  40. const { pdfUrl } = this.$route.query
  41. if (pdfUrl) {
  42. this.pdfUrl = decodeURIComponent(pdfUrl)
  43. }
  44. else {
  45. const pdfAssets = getAssetsFile('example-min.pdf')
  46. this.pdfUrl = pdfAssets
  47. }
  48. },
  49. mounted() {
  50. const container = document.getElementById('pdf-view-container')
  51. this.loadPdf(this.pdfUrl, container)
  52. // 监听窗口的 resize 事件,实现自适应效果
  53. window.addEventListener('resize', () => {
  54. container.innerHTML = ''
  55. this.loadPdf(this.pdfUrl, container)
  56. })
  57. },
  58. methods: {
  59. async loadPdf(pdfUrl, container) {
  60. try {
  61. const loadingTask = pdfjsLib.getDocument({
  62. url: pdfUrl,
  63. disableRange: true,
  64. disableAutoFetch: false, // 启动自动分块加载
  65. // 添加缓存头
  66. httpHeaders: {
  67. 'Cache-Control': 'max-age=3600' // 缓存 1 小时
  68. },
  69. // 增加网络请求超时时间,避免因网络问题导致加载失败
  70. timeout: 30000,
  71. // 减少初始加载的字节数,提高初始加载速度
  72. initialDataSize: 1024 * 1024
  73. })
  74. pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.mjs'
  75. this.pdf = await loadingTask.promise
  76. this.totalPages = this.pdf.numPages
  77. this.currentPage = 1
  78. this.batchSize = 5 // 新增
  79. await this.loadBatchPages(container) // 新增
  80. // 监听滚动事件
  81. container.addEventListener('scroll', () => this.handleScroll(container))
  82. }
  83. catch (error) {
  84. console.error('Error loading PDF:', error)
  85. }
  86. },
  87. async loadBatchPages(container) {
  88. // 加载当前页码开始的连续多页,这里以5页为例
  89. // 分批加载,从当前页码开始,最多加载5页
  90. const endPage = Math.min(this.currentPage + this.batchSize - 1, this.totalPages)
  91. for (let pageNum = this.currentPage; pageNum <= endPage; pageNum++) {
  92. const page = await this.pdf.getPage(pageNum)
  93. const viewport = page.getViewport({ scale: this.calculateScale(page) })
  94. const canvas = document.createElement('canvas')
  95. const ctx = canvas.getContext('2d')
  96. canvas.height = viewport.height
  97. canvas.width = viewport.width
  98. container.appendChild(canvas)
  99. await page.render({
  100. canvasContext: ctx,
  101. viewport,
  102. }).promise
  103. }
  104. this.currentPage = endPage + 1 // 更新当前页码
  105. },
  106. handleScroll(container) {
  107. const { scrollTop, scrollHeight, clientHeight } = container
  108. if (scrollTop + clientHeight >= scrollHeight - 100) { // 当滚动到底部附近时
  109. if (this.currentPage <= this.totalPages) {
  110. this.loadBatchPages(container)
  111. }
  112. }
  113. },
  114. // 计算缩放比例以适应容器宽度
  115. calculateScale(page) {
  116. const containerWidth = document.getElementById('pdf-view-container').clientWidth
  117. const viewport = page.getViewport({ scale: 1 })
  118. return containerWidth / viewport.width
  119. }
  120. }
  121. }
  122. </script>