From 14726a55922218b714859a1fa02f5ada8c06141d Mon Sep 17 00:00:00 2001 From: chenhao Date: Tue, 6 Jan 2026 09:18:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(purchase):=20=E6=B7=BB=E5=8A=A0PDF?= =?UTF-8?q?=E9=A2=84=E8=A7=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 集成vue-pdf-embed组件实现PDF预览功能 - 添加PDF预览弹窗界面和样式 - 实现PDF文件检测和预览逻辑 - 添加PDF加载成功和失败的处理机制 - 更新依赖包配置,添加pdfjs-dist和vue-pdf-embed - 修复包依赖顺序和重复项问题 --- package.json | 18 +++---- src/views/PurchaseDetail/index.vue | 77 +++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 61eb438..224927f 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,14 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { - "vue": "^3.3.4", - "vue-router": "^4.2.4", + "@vant/touch-emulator": "^1.4.0", + "axios": "^1.5.0", + "pdfjs-dist": "^5.4.449", "pinia": "^2.1.6", "vant": "^4.6.6", - "axios": "^1.5.0", - "@vant/touch-emulator": "^1.4.0" + "vue": "^3.3.4", + "vue-pdf-embed": "^2.1.3", + "vue-router": "^4.2.4" }, "devDependencies": { "@types/node": "^20.5.9", @@ -29,9 +31,9 @@ "prettier": "^3.0.2", "sass": "^1.66.1", "typescript": "~5.1.6", - "vite": "^4.4.9", - "vue-tsc": "^1.8.8", "unplugin-auto-import": "^0.16.6", - "unplugin-vue-components": "^0.25.2" + "unplugin-vue-components": "^0.25.2", + "vite": "^4.4.9", + "vue-tsc": "^1.8.8" } -} \ No newline at end of file +} diff --git a/src/views/PurchaseDetail/index.vue b/src/views/PurchaseDetail/index.vue index 564622f..130cccb 100644 --- a/src/views/PurchaseDetail/index.vue +++ b/src/views/PurchaseDetail/index.vue @@ -276,6 +276,26 @@ + + +
+
+ +
+
+
@@ -288,6 +308,13 @@ import { usePurchaseStore } from '@/store/purchase' import { getPurchaseApprovalHistory, submitPurchaseApproval } from '@/api/purchase' import { formatAmount, formatDate, getApprovalStatusColor, getFilePreviewUrl } from '@/utils' import type {ApprovalStatus, ApproveBtn, AttachmentFile, FileType} from '@/types' +import VuePdfEmbed from 'vue-pdf-embed' +import * as pdfjsLib from 'pdfjs-dist' + +// 设置 PDF worker +// 使用 import.meta.url 来确保在 Vite 环境下正确加载 worker +const workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.js', import.meta.url).toString() +pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc const route = useRoute() const router = useRouter() @@ -302,6 +329,9 @@ const approvalHistory = ref([]) // 审批相关 const approvalDialogVisible = ref(false) +const pdfPreviewVisible = ref(false) +const pdfUrl = ref('') +const pdfLoading = ref(false) const approvalOpinion = ref('') const currentApprovalStatus = ref(3) const submitting = ref(false) @@ -347,7 +377,25 @@ const previewFile = (file: AttachmentFile) => { } const url = getFilePreviewUrl(file.filePath) - window.open(url, '_blank') + const isPdf = file.fileName?.toLowerCase().endsWith('.pdf') || file.filePath?.toLowerCase().endsWith('.pdf') + + if (isPdf) { + pdfUrl.value = url + pdfPreviewVisible.value = true + pdfLoading.value = true + } else { + window.open(url, '_blank') + } +} + +const handlePdfLoaded = () => { + pdfLoading.value = true +} + +const handlePdfError = (error: any) => { + console.error('PDF加载失败:', error) + pdfLoading.value = false + showToast('PDF加载失败') } // 计算总金额 @@ -887,4 +935,31 @@ onMounted(async () => { background: var(--background-color-secondary); } } + +.pdf-preview-container { + height: 100%; + padding-top: 40px; + background: var(--background-color-secondary); + overflow-y: auto; + -webkit-overflow-scrolling: touch; + position: relative; +} + +.pdf-loading { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10; +} + +.pdf-content { + min-height: 100%; + background: white; +} + +.vue-pdf-embed { + width: 100%; + display: block; +}