feat(pdf): 添加pdf-vue3依赖并实现新版PDF查看组件
添加pdf-vue3依赖包用于PDF文件预览 创建PdfViewer组件替换原有PdfPreview组件 优化PDF加载性能并添加进度显示和错误处理 在StudyDetailPage中使用新组件并添加文件大小显示
Showing
6 changed files
with
46 additions
and
5 deletions
| ... | @@ -35,6 +35,7 @@ | ... | @@ -35,6 +35,7 @@ |
| 35 | "browser-md5-file": "^1.1.1", | 35 | "browser-md5-file": "^1.1.1", |
| 36 | "dayjs": "^1.11.13", | 36 | "dayjs": "^1.11.13", |
| 37 | "lodash": "^4.17.21", | 37 | "lodash": "^4.17.21", |
| 38 | + "pdf-vue3": "^1.0.12", | ||
| 38 | "swiper": "^11.2.6", | 39 | "swiper": "^11.2.6", |
| 39 | "uuid": "^11.1.0", | 40 | "uuid": "^11.1.0", |
| 40 | "vant": "^4.9.19", | 41 | "vant": "^4.9.19", | ... | ... |
| ... | @@ -18,6 +18,7 @@ declare module 'vue' { | ... | @@ -18,6 +18,7 @@ declare module 'vue' { |
| 18 | CourseCard: typeof import('./components/ui/CourseCard.vue')['default'] | 18 | CourseCard: typeof import('./components/ui/CourseCard.vue')['default'] |
| 19 | CourseImageCard: typeof import('./components/ui/CourseImageCard.vue')['default'] | 19 | CourseImageCard: typeof import('./components/ui/CourseImageCard.vue')['default'] |
| 20 | CourseList: typeof import('./components/courses/CourseList.vue')['default'] | 20 | CourseList: typeof import('./components/courses/CourseList.vue')['default'] |
| 21 | + FilePreviewPopup: typeof import('./components/ui/FilePreviewPopup.vue')['default'] | ||
| 21 | FormPage: typeof import('./components/infoEntry/formPage.vue')['default'] | 22 | FormPage: typeof import('./components/infoEntry/formPage.vue')['default'] |
| 22 | FrostedGlass: typeof import('./components/ui/FrostedGlass.vue')['default'] | 23 | FrostedGlass: typeof import('./components/ui/FrostedGlass.vue')['default'] |
| 23 | GradientHeader: typeof import('./components/ui/GradientHeader.vue')['default'] | 24 | GradientHeader: typeof import('./components/ui/GradientHeader.vue')['default'] |
| ... | @@ -25,6 +26,7 @@ declare module 'vue' { | ... | @@ -25,6 +26,7 @@ declare module 'vue' { |
| 25 | MenuItem: typeof import('./components/ui/MenuItem.vue')['default'] | 26 | MenuItem: typeof import('./components/ui/MenuItem.vue')['default'] |
| 26 | OfficeViewer: typeof import('./components/ui/OfficeViewer.vue')['default'] | 27 | OfficeViewer: typeof import('./components/ui/OfficeViewer.vue')['default'] |
| 27 | PdfPreview: typeof import('./components/ui/PdfPreview.vue')['default'] | 28 | PdfPreview: typeof import('./components/ui/PdfPreview.vue')['default'] |
| 29 | + PdfViewer: typeof import('./components/ui/PdfViewer.vue')['default'] | ||
| 28 | ReviewPopup: typeof import('./components/courses/ReviewPopup.vue')['default'] | 30 | ReviewPopup: typeof import('./components/courses/ReviewPopup.vue')['default'] |
| 29 | RouterLink: typeof import('vue-router')['RouterLink'] | 31 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 30 | RouterView: typeof import('vue-router')['RouterView'] | 32 | RouterView: typeof import('vue-router')['RouterView'] | ... | ... |
| ... | @@ -79,12 +79,29 @@ const initPdfViewer = () => { | ... | @@ -79,12 +79,29 @@ const initPdfViewer = () => { |
| 79 | // customPdfOption是 pdfjs getDocument 函数中一些配置参数 具体可参考 https://mozilla.github.io/pdf.js/api/draft/module-pdfjsLib.html#~DocumentInitParameters | 79 | // customPdfOption是 pdfjs getDocument 函数中一些配置参数 具体可参考 https://mozilla.github.io/pdf.js/api/draft/module-pdfjsLib.html#~DocumentInitParameters |
| 80 | cMapPacked: true, //指定 CMap 是否是二进制打包的 | 80 | cMapPacked: true, //指定 CMap 是否是二进制打包的 |
| 81 | cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.2.228/cmaps/", //预定义 Adobe CMaps 所在的 URL。可解决字体加载错误 | 81 | cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.2.228/cmaps/", //预定义 Adobe CMaps 所在的 URL。可解决字体加载错误 |
| 82 | + // 内存优化配置 | ||
| 83 | + disableAutoFetch: true, // 启用自动获取,提升加载速度 | ||
| 84 | + disableStream: true, // 启用流式加载 | ||
| 85 | + disableRange: true, // 启用范围请求,支持分片下载 | ||
| 86 | + // maxImageSize: 1 * 1024 * 1024, // 限制图片最大尺寸为1MB | ||
| 87 | + isEvalSupported: false, // 禁用eval,提升安全性和性能 | ||
| 88 | + // 启用懒加载,减少内存占用 | ||
| 89 | + enableXfa: true, // 禁用XFA表单支持,减少内存占用 | ||
| 90 | + // 添加更多性能优化配置 | ||
| 91 | + useOnlyCssZoom: true, // 仅使用CSS缩放,减少重新渲染 | ||
| 92 | + verbosity: 0, // 减少日志输出,提升性能 | ||
| 93 | + // 微信浏览器优化配置 | ||
| 94 | + useWorkerFetch: true, // 在微信浏览器中禁用Worker fetch,避免兼容性问题 | ||
| 95 | + disableFontFace: true, // 保持字体渲染,但可能需要根据情况调整 | ||
| 96 | + // 内存管理配置 | ||
| 97 | + pdfBug: true, // 禁用调试模式,减少内存占用 | ||
| 98 | + stopAtErrors: true, // 不要在错误时停止,让错误回调处理 | ||
| 82 | }, | 99 | }, |
| 83 | // 禁用右键菜单和文本选择 | 100 | // 禁用右键菜单和文本选择 |
| 84 | selectConfig: undefined, // 禁用文本选择功能 | 101 | selectConfig: undefined, // 禁用文本选择功能 |
| 85 | } | 102 | } |
| 86 | }); | 103 | }); |
| 87 | - | 104 | + |
| 88 | // 添加额外的事件监听器来防止长按保存 | 105 | // 添加额外的事件监听器来防止长按保存 |
| 89 | const pdfContainer = document.querySelector("#pdf-container"); | 106 | const pdfContainer = document.querySelector("#pdf-container"); |
| 90 | if (pdfContainer) { | 107 | if (pdfContainer) { |
| ... | @@ -93,13 +110,13 @@ const initPdfViewer = () => { | ... | @@ -93,13 +110,13 @@ const initPdfViewer = () => { |
| 93 | e.preventDefault(); | 110 | e.preventDefault(); |
| 94 | return false; | 111 | return false; |
| 95 | }); | 112 | }); |
| 96 | - | 113 | + |
| 97 | // 防止长按选择 | 114 | // 防止长按选择 |
| 98 | pdfContainer.addEventListener('selectstart', (e) => { | 115 | pdfContainer.addEventListener('selectstart', (e) => { |
| 99 | e.preventDefault(); | 116 | e.preventDefault(); |
| 100 | return false; | 117 | return false; |
| 101 | }); | 118 | }); |
| 102 | - | 119 | + |
| 103 | // 防止拖拽 | 120 | // 防止拖拽 |
| 104 | pdfContainer.addEventListener('dragstart', (e) => { | 121 | pdfContainer.addEventListener('dragstart', (e) => { |
| 105 | e.preventDefault(); | 122 | e.preventDefault(); | ... | ... |
src/components/ui/PdfViewer.vue
0 → 100644
This diff is collapsed. Click to expand it.
| ... | @@ -261,7 +261,7 @@ | ... | @@ -261,7 +261,7 @@ |
| 261 | </van-popup> | 261 | </van-popup> |
| 262 | 262 | ||
| 263 | <!-- PDF预览 --> | 263 | <!-- PDF预览 --> |
| 264 | - <PdfPreview v-model:show="pdfShow" :url="pdfUrl" :title="pdfTitle" @onLoad="onPdfLoad" /> | 264 | + <PdfViewer v-model:show="pdfShow" :url="pdfUrl" :title="pdfTitle" @onLoad="onPdfLoad" @onProgress="onPdfProgress" @onComplete="onPdfComplete" /> |
| 265 | 265 | ||
| 266 | <!-- Office 文档预览弹窗 --> | 266 | <!-- Office 文档预览弹窗 --> |
| 267 | <van-popup | 267 | <van-popup |
| ... | @@ -536,6 +536,7 @@ | ... | @@ -536,6 +536,7 @@ |
| 536 | <div class="flex items-center gap-1"> | 536 | <div class="flex items-center gap-1"> |
| 537 | <van-icon name="label-o" size="12" style="margin-right: 0.25rem;"/> | 537 | <van-icon name="label-o" size="12" style="margin-right: 0.25rem;"/> |
| 538 | <span>{{ getFileType(file.title || file.name) }}</span> | 538 | <span>{{ getFileType(file.title || file.name) }}</span> |
| 539 | + <span class="ml-2">{{ file.size ? (file.size / 1024 / 1024).toFixed(2) + 'MB' : '' }}</span> | ||
| 539 | </div> | 540 | </div> |
| 540 | <!-- 复制地址按钮 --> | 541 | <!-- 复制地址按钮 --> |
| 541 | <!-- <button | 542 | <!-- <button |
| ... | @@ -656,7 +657,7 @@ import { formatDate, wxInfo } from '@/utils/tools' | ... | @@ -656,7 +657,7 @@ import { formatDate, wxInfo } from '@/utils/tools' |
| 656 | import axios from 'axios'; | 657 | import axios from 'axios'; |
| 657 | import { v4 as uuidv4 } from "uuid"; | 658 | import { v4 as uuidv4 } from "uuid"; |
| 658 | import { useIntersectionObserver } from '@vueuse/core'; | 659 | import { useIntersectionObserver } from '@vueuse/core'; |
| 659 | -import PdfPreview from '@/components/ui/PdfPreview.vue'; | 660 | +import PdfViewer from '@/components/ui/PdfViewer.vue'; |
| 660 | import { showToast } from 'vant'; | 661 | import { showToast } from 'vant'; |
| 661 | 662 | ||
| 662 | // 导入接口 | 663 | // 导入接口 |
| ... | @@ -986,6 +987,21 @@ const onPdfLoad = (load) => { | ... | @@ -986,6 +987,21 @@ const onPdfLoad = (load) => { |
| 986 | }; | 987 | }; |
| 987 | 988 | ||
| 988 | /** | 989 | /** |
| 990 | + * PDF下载进度回调 | ||
| 991 | + * @param {number} progress - 下载进度 0-100 | ||
| 992 | + */ | ||
| 993 | +const onPdfProgress = (progress) => { | ||
| 994 | + // console.log('PDF下载进度:', progress); | ||
| 995 | +}; | ||
| 996 | + | ||
| 997 | +/** | ||
| 998 | + * PDF下载完成回调 | ||
| 999 | + */ | ||
| 1000 | +const onPdfComplete = () => { | ||
| 1001 | + // console.log('PDF下载完成'); | ||
| 1002 | +}; | ||
| 1003 | + | ||
| 1004 | +/** | ||
| 989 | * Office 文档渲染完成回调 | 1005 | * Office 文档渲染完成回调 |
| 990 | */ | 1006 | */ |
| 991 | const onOfficeRendered = () => { | 1007 | const onOfficeRendered = () => { | ... | ... |
| ... | @@ -2124,6 +2124,11 @@ pathe@^2.0.1, pathe@^2.0.2, pathe@^2.0.3: | ... | @@ -2124,6 +2124,11 @@ pathe@^2.0.1, pathe@^2.0.2, pathe@^2.0.3: |
| 2124 | resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" | 2124 | resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" |
| 2125 | integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== | 2125 | integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== |
| 2126 | 2126 | ||
| 2127 | +pdf-vue3@^1.0.12: | ||
| 2128 | + version "1.0.12" | ||
| 2129 | + resolved "https://registry.npmjs.org/pdf-vue3/-/pdf-vue3-1.0.12.tgz#8b2c4346cd75a7d3307aa6117c591c047549f4ed" | ||
| 2130 | + integrity sha512-7SMTx1RfRwdc+2WPniDzqM8MxJLqTNNzdyV0SeQTxeRLJGndb5Wv/fz5afO13oBSIvvaqcbZ/S3gF+XjqkSb9g== | ||
| 2131 | + | ||
| 2127 | pdfjs-dist@3.4.120: | 2132 | pdfjs-dist@3.4.120: |
| 2128 | version "3.4.120" | 2133 | version "3.4.120" |
| 2129 | resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-3.4.120.tgz#6f4222117157498f179c95dc4569fad6336a8fdd" | 2134 | resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-3.4.120.tgz#6f4222117157498f179c95dc4569fad6336a8fdd" | ... | ... |
-
Please register or login to post a comment