Browse Source

feat: 新增文章PDF预览

zhangyuhan 7 months ago
parent
commit
ed81d68aea

+ 27 - 2
apps/bigmember_pc/src/assets/style/page/article.scss

@@ -2,7 +2,6 @@
 
 .article-page-container {
   ::v-deep {
-
     .free-view {
       cursor: pointer;
     }
@@ -299,5 +298,31 @@
       line-height: normal;
     }
   }
-}
 
+  .preview-pdf-container {
+    position: relative;
+    margin: 12px 0;
+
+    .preview-pdf-scroll {
+      overflow: auto;
+    }
+
+    .preview-pdf-header {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: center;
+      background: #4e4e4e;
+      color: #fff;
+      font-size: 14px;
+      padding: 12px;
+    }
+  }
+  .preview-pdf-img {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: -1;
+    opacity: 0;
+  }
+}

+ 105 - 0
apps/bigmember_pc/src/views/article-content/pages/Article.vue

@@ -264,6 +264,85 @@ const handleFocus = () => {
   }
 }
 
+// PDF 预览
+const pdfPreviewInfo = ref({
+  show: false,
+  url: '',
+  num: '',
+  total: '',
+  originHeight: 0,
+  height: 'auto'
+})
+const pdfDocument = ref(null)
+const config = {
+  PAGE_TO_VIEW: 0,
+  SCALE: 1.0,
+  CMAP_URL:
+    'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/cmaps/',
+  CMAP_PACKED: true,
+  workerSrc:
+    'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.worker.min.js'
+}
+
+function initPreviewPdf() {
+  function renders(id) {
+    return pdfDocument.value.getPage(id).then((pdfPage) => {
+      var pdfPageView = new pdfjsViewer.PDFPageView({
+        container: document.getElementById('previewPdfContainer'),
+        id: id,
+        scale: config.SCALE,
+        defaultViewport: pdfPage.getViewport({ scale: config.SCALE }),
+        eventBus: new pdfjsViewer.EventBus(),
+        annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory()
+      })
+      pdfPageView.setPdfPage(pdfPage)
+      pdfPreviewInfo.value.originHeight = pdfPageView.viewport.height
+      if (pdfPreviewInfo.value.height === 'auto') {
+        pdfPreviewInfo.value.height = pdfPageView.viewport.height * 0.8 + 'px'
+      }
+      return pdfPageView.draw()
+    })
+  }
+  function init() {
+    pdfjsLib.GlobalWorkerOptions.workerSrc = config.workerSrc
+    const loadingTask = pdfjsLib.getDocument({
+      url: pdfPreviewInfo.value.url,
+      cMapUrl: config.CMAP_URL,
+      cMapPacked: config.CMAP_PACKED
+    })
+    loadingTask.promise
+      .then((pdfDocumentNode) => {
+        pdfDocument.value = pdfDocumentNode
+        pdfPreviewInfo.value.total = pdfDocumentNode.numPages
+        pdfPreviewInfo.value.num = 1
+
+        for (let i = 0; i < pdfPreviewInfo.value.total; i++) {
+          renders(i + 1)
+        }
+        pdfPreviewInfo.value.loading = false
+        pdfPreviewInfo.value.state = true
+      })
+      .catch((e) => {
+        console.warn('-------PDF ERROR------')
+        console.warn(e)
+        pdfPreviewInfo.value.loading = false
+        pdfPreviewInfo.value.state = false
+      })
+  }
+
+  if (ContentModel.value._od.pdfUrl) {
+    pdfPreviewInfo.value.show = true
+    pdfPreviewInfo.value.url = ContentModel.value._od.pdfUrl
+    init()
+  }
+}
+
+function computedPdfPageNum(e) {
+  const pTop = e.target.scrollTop
+  pdfPreviewInfo.value.num =
+    Math.floor(pTop / pdfPreviewInfo.value.originHeight) + 1
+}
+
 onMounted(() => {
   addRightDom()
   window.addEventListener('scroll', handleScroll)
@@ -572,7 +651,33 @@ const sunLeaveInfo = () => {
                     </div>
                   </template>
                   <template v-else>
+                    <img
+                      class="preview-pdf-img"
+                      src="https://cdn-ali.jianyu360.com/images/collect.png"
+                      @load="initPreviewPdf"
+                    />
+
+                    <div
+                      class="preview-pdf-container"
+                      v-if="pdfPreviewInfo.show"
+                    >
+                      <div class="preview-pdf-header">
+                        {{ pdfPreviewInfo.num }} / {{ pdfPreviewInfo.total }}
+                      </div>
+                      <div
+                        class="preview-pdf-scroll"
+                        :style="{ height: pdfPreviewInfo.height }"
+                        @scroll="computedPdfPageNum"
+                      >
+                        <div
+                          class="preview-pdf-dom"
+                          id="previewPdfContainer"
+                        ></div>
+                      </div>
+                    </div>
+
                     <div
+                      v-else
                       class="content-detail-container"
                       v-event-listener:click="doClickFreeView"
                       data-event-selector=".free-view"

+ 3 - 1
apps/bigmember_pc/vite.config.js

@@ -19,7 +19,9 @@ const baseCDN = {
   ],
   js: [
     'https://cdn-common.jianyu360.com/cdn/lib/echarts/4.8.0/echarts.min.js',
-    'https://cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/index.min.js'
+    'https://cdn-common.jianyu360.com/cdn/lib/v-charts/1.19.0/index.min.js',
+    'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.min.js',
+    'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/web/pdf_viewer.js'
     // 'https://cdn-common.jianyu360.com/cdn/lib/jquery/3.5.1/jquery.min.js', // 标签上需要添加ignore
   ]
 }

+ 3 - 1
eslint.config.mjs

@@ -21,7 +21,9 @@ export default antfu({
   },
   languageOptions: {
     globals: {
-      JyObj: true
+      JyObj: true,
+      pdfjsLib: true,
+      pdfjsViewer: true
     }
   }
 })