|
|
@@ -1,132 +1,61 @@
|
|
|
<template>
|
|
|
- <div class="pdf-container">
|
|
|
- <canvas ref="pdfCanvas"></canvas>
|
|
|
- <p v-if="errorMsg" class="error">{{ errorMsg }}</p>
|
|
|
- <div v-if="loading" class="loader">加载中...</div>
|
|
|
+ <div>
|
|
|
+ <iframe class="pdf-container" :src="processedSrc" frameborder="0" style="width: 100%; height: 800px;"></iframe>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { getDocument } from 'pdfjs-dist/build/pdf'; // 确保使用最新API
|
|
|
-import * as pdfjsLib from 'pdfjs-dist'; // 全局命名空间备用
|
|
|
-
|
|
|
export default {
|
|
|
name: "pdfViewer",
|
|
|
- // props: {
|
|
|
- // src: { type: String, required: true }, // PDF文件URL或Base64数据
|
|
|
- // pageNum: { type: Number, default: 1 } // 可选参数:指定显示哪一页
|
|
|
- // },
|
|
|
- props:['src','pageNum'],
|
|
|
+ props: {
|
|
|
+ src: { type: String, required: true }, // ✅ 明确声明为必填项
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
- pdfDoc: null,
|
|
|
- loading: true,
|
|
|
- errorMsg: null
|
|
|
+ processedSrc: '' // 存储处理后的最终URL
|
|
|
};
|
|
|
},
|
|
|
- created() {
|
|
|
- // ✅ 关键:提前注册Worker以避免竞态条件
|
|
|
- pdfjsLib.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.entry');
|
|
|
- },
|
|
|
- async mounted() {
|
|
|
- try {
|
|
|
- const doc = await getDocument({ url: this.src, withCredentials: true }).promise;
|
|
|
- this.pdfDoc = doc;
|
|
|
- await this.renderPage(this.pageNum);
|
|
|
- this.loading = false;
|
|
|
- } catch (err) {
|
|
|
- console.error("🔍 详细错误堆栈:", err); // 输出完整错误上下文
|
|
|
- this.errorMsg = `加载失败 · ${err.message}`;
|
|
|
- this.loading = false;
|
|
|
- }
|
|
|
- },
|
|
|
methods:{
|
|
|
- async loadNewDocument(newSrc) { // 新增的核心方法!
|
|
|
- console.log(newSrc,'newSrc')
|
|
|
+ normalizeUrl(rawUrl) {
|
|
|
try {
|
|
|
- this.loading = true;
|
|
|
- this.errorMsg = null;
|
|
|
- const docPromise = getDocument({ url: newSrc, withCredentials: true });
|
|
|
- this.pdfDoc = await docPromise.promise;
|
|
|
- await this.renderPage(this.pageNum);
|
|
|
- this.loading = false;
|
|
|
- } catch (err) {
|
|
|
- console.error("新文档加载失败:", err);
|
|
|
- this.errorMsg = `无法加载新PDF文件 (${err.message})`;
|
|
|
- this.loading = false;
|
|
|
+ const urlObj = new URL(rawUrl);
|
|
|
+ if (urlObj.protocol === 'http:') {
|
|
|
+ urlObj.protocol = 'https:'; // 强制升级到HTTPS
|
|
|
+ return urlObj.toString();
|
|
|
+ }
|
|
|
+ return rawUrl;
|
|
|
+ } catch (e) {
|
|
|
+ console.error('❌ URL解析失败:', e);
|
|
|
+ throw new Error('无效的PDF链接格式'); // 主动抛出可捕获的错误
|
|
|
}
|
|
|
},
|
|
|
- async renderPage(pageNumber) {
|
|
|
- if (!this.pdfDoc) return;
|
|
|
-
|
|
|
- try {
|
|
|
- const page = await this.pdfDoc.getPage(pageNumber);
|
|
|
- const canvas = this.$refs.pdfCanvas;
|
|
|
- const context = canvas.getContext('2d');
|
|
|
-
|
|
|
- // 动态计算最佳缩放比例以适应容器
|
|
|
- const scaleFactor = Math.min(
|
|
|
- this.$el.clientWidth / page.view[2],
|
|
|
- this.$el.clientHeight / page.view[3]
|
|
|
- );
|
|
|
- const viewport = page.getViewport({ scale: scaleFactor });
|
|
|
-
|
|
|
- // 更新画布尺寸并清除旧内容
|
|
|
- canvas.width = viewport.width;
|
|
|
- canvas.height = viewport.height;
|
|
|
- context.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
-
|
|
|
- // 执行实际渲染操作
|
|
|
- await page.render({
|
|
|
- canvasContext: context,
|
|
|
- viewport: viewport,
|
|
|
- intent: 'display' // 确保高质量输出
|
|
|
- }).promise;
|
|
|
- } catch (err) {
|
|
|
- console.error(`第${pageNumber}页渲染失败`, err);
|
|
|
- this.errorMsg = `页面 ${pageNumber} 渲染出错`;
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- watch: {
|
|
|
- src: {
|
|
|
- handler: function(newVal) {
|
|
|
- if (!newVal) return;
|
|
|
- this.loading = true;
|
|
|
- this.errorMsg = null;
|
|
|
- this.loadNewDocument(newVal);
|
|
|
- },
|
|
|
- immediate: true
|
|
|
+ loadNewDocument(finalUrl) {
|
|
|
+ this.processedSrc = finalUrl; // 更新响应式数据驱动视图更新
|
|
|
}
|
|
|
},
|
|
|
- beforeDestroy() {
|
|
|
- // 清理Worker防止内存泄漏
|
|
|
- if (pdfjsLib.GlobalWorkerOptions.worker) {
|
|
|
- pdfjsLib.GlobalWorkerOptions.worker.terminate();
|
|
|
+ mounted() {
|
|
|
+ try {
|
|
|
+ const safeUrl = this.normalizeUrl(this.src); // ✅ 正确使用 this.src
|
|
|
+ this.loadNewDocument(safeUrl);
|
|
|
+ } catch (err) {
|
|
|
+ console.error('🚀 初始化加载失败:', err);
|
|
|
+ // 可根据业务需求添加降级处理逻辑
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
+/* 保持原有样式不变 */
|
|
|
.pdf-container {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
- max-height: 80vh; /* 限制最大可视高度 */
|
|
|
+ max-height: 80vh;
|
|
|
border: 1px solid #eee;
|
|
|
}
|
|
|
-canvas {
|
|
|
+iframe {
|
|
|
display: block;
|
|
|
- margin: auto; /* 居中显示 */
|
|
|
+ margin: auto;
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
}
|
|
|
-.error {
|
|
|
- color: red;
|
|
|
- text-align: center;
|
|
|
- padding: 1rem;
|
|
|
-}
|
|
|
-.loader {
|
|
|
- text-align: center;
|
|
|
- padding: 2rem;
|
|
|
-}
|
|
|
</style>
|