@eternalheart/vue-file-preview 1.3.13 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/lib/FilePreviewContent.vue.d.ts +3 -0
  2. package/lib/FilePreviewContent.vue.d.ts.map +1 -1
  3. package/lib/FilePreviewEmbed.vue.d.ts +5 -0
  4. package/lib/FilePreviewEmbed.vue.d.ts.map +1 -1
  5. package/lib/FilePreviewModal.vue.d.ts.map +1 -1
  6. package/lib/chunks/{RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs → RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs} +9 -9
  7. package/lib/chunks/RendererError.vue_vue_type_script_setup_true_lang-BNoENOWX.mjs.map +1 -0
  8. package/lib/chunks/index-8ETACZ6T.mjs +267 -0
  9. package/lib/chunks/index-8ETACZ6T.mjs.map +1 -0
  10. package/lib/chunks/{index-DyipSoKh.mjs → index-B-LW-GJO.mjs} +24 -21
  11. package/lib/chunks/index-B-LW-GJO.mjs.map +1 -0
  12. package/lib/chunks/{index-Cjnw238n.mjs → index-BT9hXA6r.mjs} +3 -3
  13. package/lib/chunks/{index-Cjnw238n.mjs.map → index-BT9hXA6r.mjs.map} +1 -1
  14. package/lib/chunks/{index-CyrFxdIJ.mjs → index-BcKI75RW.mjs} +4 -4
  15. package/lib/chunks/{index-CyrFxdIJ.mjs.map → index-BcKI75RW.mjs.map} +1 -1
  16. package/lib/chunks/{index-Ctd0JQ6K.mjs → index-By6vGdnK.mjs} +3 -3
  17. package/lib/chunks/{index-Ctd0JQ6K.mjs.map → index-By6vGdnK.mjs.map} +1 -1
  18. package/lib/chunks/{index-BHi1WRQZ.mjs → index-C-Mu0fvH.mjs} +3 -3
  19. package/lib/chunks/{index-BHi1WRQZ.mjs.map → index-C-Mu0fvH.mjs.map} +1 -1
  20. package/lib/chunks/{index-DT9dPz8I.mjs → index-CGSq7-Q-.mjs} +3 -3
  21. package/lib/chunks/{index-DT9dPz8I.mjs.map → index-CGSq7-Q-.mjs.map} +1 -1
  22. package/lib/chunks/{index-DTtHrdBl.mjs → index-CWpU8prZ.mjs} +11 -11
  23. package/lib/chunks/index-CWpU8prZ.mjs.map +1 -0
  24. package/lib/chunks/index-CYa_XneH.mjs +303 -0
  25. package/lib/chunks/index-CYa_XneH.mjs.map +1 -0
  26. package/lib/chunks/{index-CYt6tpQC.mjs → index-CbJkkdEB.mjs} +9 -9
  27. package/lib/chunks/index-CbJkkdEB.mjs.map +1 -0
  28. package/lib/chunks/{index-DEoR7aDN.mjs → index-CoITLoYL.mjs} +3 -3
  29. package/lib/chunks/{index-DEoR7aDN.mjs.map → index-CoITLoYL.mjs.map} +1 -1
  30. package/lib/chunks/{index-Oxwizt6-.mjs → index-D9QQL7U6.mjs} +605 -557
  31. package/lib/chunks/index-D9QQL7U6.mjs.map +1 -0
  32. package/lib/chunks/{index-BvegaxQF.mjs → index-DAdO2lkI.mjs} +32 -32
  33. package/lib/chunks/index-DAdO2lkI.mjs.map +1 -0
  34. package/lib/chunks/{index-GGGDPwxX.mjs → index-DGqDJMot.mjs} +3 -3
  35. package/lib/chunks/{index-GGGDPwxX.mjs.map → index-DGqDJMot.mjs.map} +1 -1
  36. package/lib/chunks/{index-DIe0vHlt.mjs → index-DTyG1Wzp.mjs} +8 -8
  37. package/lib/chunks/index-DTyG1Wzp.mjs.map +1 -0
  38. package/lib/chunks/{index-Dw1U4YqT.mjs → index-DglMeKJM.mjs} +36 -38
  39. package/lib/chunks/{index-Dw1U4YqT.mjs.map → index-DglMeKJM.mjs.map} +1 -1
  40. package/lib/chunks/{index-B2lqsdp7.mjs → index-OOoaYpkl.mjs} +3 -3
  41. package/lib/chunks/{index-B2lqsdp7.mjs.map → index-OOoaYpkl.mjs.map} +1 -1
  42. package/lib/chunks/{index-DBw8tvyb.mjs → index-jcgLzyDR.mjs} +4 -4
  43. package/lib/chunks/{index-DBw8tvyb.mjs.map → index-jcgLzyDR.mjs.map} +1 -1
  44. package/lib/chunks/{index-BTW1xwB9.mjs → index-nFIiu1lA.mjs} +3 -3
  45. package/lib/chunks/{index-BTW1xwB9.mjs.map → index-nFIiu1lA.mjs.map} +1 -1
  46. package/lib/index.cjs +40 -32
  47. package/lib/index.cjs.map +1 -1
  48. package/lib/index.css +1 -1
  49. package/lib/index.mjs +1 -1
  50. package/lib/renderers/Audio/index.vue.d.ts.map +1 -1
  51. package/lib/renderers/Docx/index.vue.d.ts.map +1 -1
  52. package/lib/renderers/Epub/index.vue.d.ts.map +1 -1
  53. package/lib/renderers/Markdown/index.vue.d.ts.map +1 -1
  54. package/lib/renderers/Pdf/index.vue.d.ts +3 -0
  55. package/lib/renderers/Pdf/index.vue.d.ts.map +1 -1
  56. package/lib/renderers/Pdf/toolbar.d.ts +5 -0
  57. package/lib/renderers/Pdf/toolbar.d.ts.map +1 -1
  58. package/lib/renderers/RendererError.vue.d.ts.map +1 -1
  59. package/lib/renderers/Subtitle/index.vue.d.ts.map +1 -1
  60. package/lib/renderers/Text/index.vue.d.ts.map +1 -1
  61. package/lib/renderers/Xml/index.vue.d.ts.map +1 -1
  62. package/package.json +1 -1
  63. package/lib/chunks/RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs.map +0 -1
  64. package/lib/chunks/index-BvegaxQF.mjs.map +0 -1
  65. package/lib/chunks/index-CYt6tpQC.mjs.map +0 -1
  66. package/lib/chunks/index-DIe0vHlt.mjs.map +0 -1
  67. package/lib/chunks/index-DTtHrdBl.mjs.map +0 -1
  68. package/lib/chunks/index-DX_NBPzS.mjs +0 -248
  69. package/lib/chunks/index-DX_NBPzS.mjs.map +0 -1
  70. package/lib/chunks/index-DyipSoKh.mjs.map +0 -1
  71. package/lib/chunks/index-Oxwizt6-.mjs.map +0 -1
  72. package/lib/chunks/index-Zwl5J-Uw.mjs +0 -166
  73. package/lib/chunks/index-Zwl5J-Uw.mjs.map +0 -1
@@ -1,166 +0,0 @@
1
- import { defineComponent as I, ref as w, onMounted as W, watch as S, onBeforeUnmount as $, openBlock as x, createElementBlock as b, createBlock as A, createCommentVNode as k, createElementVNode as R, withDirectives as F, vShow as N, toDisplayString as B, nextTick as O } from "vue";
2
- import { B as U, u as Z } from "./index-Oxwizt6-.mjs";
3
- import * as D from "pdfjs-dist/build/pdf.mjs";
4
- import { _ as M } from "./RendererError.vue_vue_type_script_setup_true_lang-CbgZBSDr.mjs";
5
- const G = {
6
- key: 1,
7
- class: "vfp-flex vfp-items-center vfp-justify-center vfp-min-h-screen"
8
- }, J = { class: "pdf-pages vfp-flex vfp-flex-col vfp-gap-4" }, K = {
9
- key: 2,
10
- class: "vfp-sticky vfp-bottom-2 md:vfp-bottom-4 vfp-mt-4 md:vfp-mt-8 vfp-bg-surface-nav-hover vfp-backdrop-blur-xl vfp-text-fg-primary vfp-px-4 vfp-py-2 md:vfp-px-6 md:vfp-py-3 vfp-rounded-full vfp-text-xs md:vfp-text-sm vfp-font-medium vfp-shadow-2xl vfp-border vfp-border-line-weak"
11
- }, ee = /* @__PURE__ */ I({
12
- components: {
13
- RendererError: M
14
- },
15
- __name: "index",
16
- props: {
17
- url: {},
18
- zoom: {},
19
- currentPage: {}
20
- },
21
- emits: ["pageChange", "totalPagesChange", "pageWidthChange"],
22
- setup(T, { emit: z }) {
23
- U(D);
24
- const u = T, g = z, { t: L } = Z(), c = w(0), f = w(null), l = w(null);
25
- let s = null;
26
- const i = /* @__PURE__ */ new Map();
27
- let a = null;
28
- const V = async (e, t) => {
29
- if (!s) return;
30
- const n = i.get(e);
31
- if (!(!n || n.rendering)) {
32
- n.rendering = !0;
33
- try {
34
- const r = await s.getPage(e), p = r.getViewport({ scale: t }), o = document.createElement("canvas");
35
- o.width = p.width, o.height = p.height, o.style.maxWidth = "100%", o.style.height = "auto", o.style.borderRadius = "0", o.style.display = "block", o.style.boxShadow = "0 25px 50px -12px rgba(0,0,0,0.25)", o.style.filter = "brightness(0.95) contrast(1.05)";
36
- const m = o.getContext("2d");
37
- if (!m) return;
38
- const h = r.render({ canvasContext: m, viewport: p });
39
- if (n.renderTask = h, await h.promise, e === 1) {
40
- const y = r.getViewport({ scale: 1 });
41
- g("pageWidthChange", y.width);
42
- }
43
- n.element.innerHTML = "", n.element.appendChild(o);
44
- const d = document.createElement("div");
45
- d.textContent = String(e), d.style.cssText = "position:absolute;top:8px;right:8px;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);color:white;font-size:12px;padding:4px 12px;border-radius:9999px;", n.element.appendChild(d), n.rendered = !0;
46
- } catch (r) {
47
- (r == null ? void 0 : r.name) !== "RenderingCancelledException" && console.error(`渲染页面 ${e} 失败:`, r);
48
- } finally {
49
- n.rendering = !1, n.renderTask = null;
50
- }
51
- }
52
- }, C = (e) => {
53
- const t = i.get(e);
54
- if (!t) return;
55
- t.renderTask && (t.renderTask.cancel(), t.renderTask = null);
56
- const n = t.element.querySelector("canvas");
57
- if (n) {
58
- const r = n.getContext("2d");
59
- r && r.clearRect(0, 0, n.width, n.height), n.remove();
60
- }
61
- t.element.innerHTML = "", t.rendered = !1, t.rendering = !1;
62
- }, H = async () => {
63
- if (!s || !l.value) return;
64
- const e = l.value.querySelector(".pdf-pages");
65
- if (e) {
66
- e.innerHTML = "", i.clear();
67
- for (let t = 1; t <= c.value; t++) {
68
- const n = document.createElement("div");
69
- n.style.cssText = "position:relative;display:flex;justify-content:center;min-height:800px;", n.dataset.pageNumber = String(t), e.appendChild(n), i.set(t, {
70
- element: n,
71
- rendered: !1,
72
- rendering: !1,
73
- renderTask: null
74
- }), a && a.observe(n);
75
- }
76
- }
77
- }, P = async () => {
78
- if (f.value = null, c.value = 0, s) {
79
- try {
80
- s.destroy();
81
- } catch {
82
- }
83
- s = null;
84
- }
85
- try {
86
- s = await D.getDocument({ url: u.url }).promise, c.value = s.numPages, g("totalPagesChange", s.numPages), g("pageChange", 1), await O(), await H();
87
- } catch (e) {
88
- console.error("PDF 加载错误:", e), f.value = L.value("pdf.load_failed");
89
- }
90
- }, E = () => {
91
- if (!l.value || i.size === 0) return;
92
- const e = l.value, t = e.scrollTop, n = e.clientHeight, r = t + n / 2;
93
- let p = 1, o = 1 / 0;
94
- i.forEach((m, h) => {
95
- const d = m.element.getBoundingClientRect(), y = e.getBoundingClientRect(), q = d.top - y.top + d.height / 2 + t, _ = Math.abs(q - r);
96
- _ < o && (o = _, p = h);
97
- }), p !== u.currentPage && g("pageChange", p);
98
- };
99
- let v = null;
100
- const j = () => {
101
- v && clearTimeout(v), v = window.setTimeout(() => {
102
- i.forEach((e, t) => {
103
- e.rendered && C(t);
104
- }), a && l.value && l.value.querySelector(".pdf-pages") && i.forEach((t) => {
105
- a == null || a.unobserve(t.element), a == null || a.observe(t.element);
106
- });
107
- }, 150);
108
- };
109
- return W(() => {
110
- a = new IntersectionObserver(
111
- (e) => {
112
- e.forEach((t) => {
113
- const n = Number(t.target.getAttribute("data-page-number"));
114
- if (n)
115
- if (t.isIntersecting)
116
- V(n, u.zoom);
117
- else {
118
- const r = i.get(n);
119
- r && r.rendered && C(n);
120
- }
121
- });
122
- },
123
- {
124
- root: l.value,
125
- rootMargin: "500px 0px",
126
- threshold: 0
127
- }
128
- ), P(), l.value && l.value.addEventListener("scroll", E);
129
- }), S(
130
- () => u.url,
131
- (e) => {
132
- e && P();
133
- }
134
- ), S(() => u.zoom, j), $(() => {
135
- if (v && clearTimeout(v), a && (a.disconnect(), a = null), l.value && l.value.removeEventListener("scroll", E), i.forEach((e) => {
136
- e.renderTask && e.renderTask.cancel();
137
- }), i.clear(), s) {
138
- try {
139
- s.destroy();
140
- } catch {
141
- }
142
- s = null;
143
- }
144
- }), (e, t) => (x(), b("div", {
145
- ref_key: "containerRef",
146
- ref: l,
147
- class: "vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full vfp-overflow-auto vfp-py-4 md:vfp-py-8 vfp-px-2 md:vfp-px-4"
148
- }, [
149
- f.value ? (x(), A(M, {
150
- key: 0,
151
- message: f.value
152
- }, null, 8, ["message"])) : k("", !0),
153
- !f.value && c.value === 0 ? (x(), b("div", G, [...t[0] || (t[0] = [
154
- R("div", { class: "vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin" }, null, -1)
155
- ])])) : k("", !0),
156
- F(R("div", J, null, 512), [
157
- [N, !f.value && c.value > 0]
158
- ]),
159
- c.value > 0 ? (x(), b("div", K, " 第 " + B(T.currentPage) + " 页 / 共 " + B(c.value) + " 页 ", 1)) : k("", !0)
160
- ], 512));
161
- }
162
- });
163
- export {
164
- ee as default
165
- };
166
- //# sourceMappingURL=index-Zwl5J-Uw.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-Zwl5J-Uw.mjs","sources":["../../src/renderers/Pdf/index.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';\nimport { configurePdfWorker } from '@eternalheart/file-preview-core';\n// @ts-ignore - pdfjs-dist 类型路径\nimport * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';\nimport { useTranslator } from '../../composables/useTranslator';\nimport RendererError from '../RendererError.vue';\n\n// 在模块加载时配置 PDF.js worker(默认走 CDN)\nconfigurePdfWorker(pdfjsLib);\n\ndefineOptions({\n components: {\n RendererError,\n },\n});\n\ninterface PdfPageProxy {\n getViewport(opts: { scale: number }): { width: number; height: number };\n render(opts: { canvasContext: CanvasRenderingContext2D; viewport: { width: number; height: number } }): {\n promise: Promise<void>;\n cancel(): void;\n };\n}\n\ninterface PdfDocumentProxy {\n numPages: number;\n getPage(pageNumber: number): Promise<PdfPageProxy>;\n destroy(): void;\n}\n\ninterface PageState {\n element: HTMLDivElement;\n rendered: boolean;\n rendering: boolean;\n renderTask: { cancel(): void } | null;\n}\n\nconst props = defineProps<{\n url: string;\n zoom: number;\n currentPage: number;\n}>();\n\nconst emit = defineEmits<{\n (e: 'pageChange', page: number): void;\n (e: 'totalPagesChange', total: number): void;\n (e: 'pageWidthChange', width: number): void;\n}>();\n\nconst { t } = useTranslator();\n\nconst numPages = ref(0);\nconst error = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nlet pdfDoc: PdfDocumentProxy | null = null;\nconst pageStates = new Map<number, PageState>();\nlet observer: IntersectionObserver | null = null;\n\nconst renderPage = async (pageNumber: number, scale: number) => {\n if (!pdfDoc) return;\n const state = pageStates.get(pageNumber);\n if (!state || state.rendering) return;\n\n state.rendering = true;\n\n try {\n const page = await pdfDoc.getPage(pageNumber);\n const viewport = page.getViewport({ scale });\n\n const canvas = document.createElement('canvas');\n canvas.width = viewport.width;\n canvas.height = viewport.height;\n canvas.style.maxWidth = '100%';\n canvas.style.height = 'auto';\n canvas.style.borderRadius = '0';\n canvas.style.display = 'block';\n canvas.style.boxShadow = '0 25px 50px -12px rgba(0,0,0,0.25)';\n canvas.style.filter = 'brightness(0.95) contrast(1.05)';\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const renderTask = page.render({ canvasContext: ctx, viewport });\n state.renderTask = renderTask;\n await renderTask.promise;\n\n // 上报第一页原始宽度\n if (pageNumber === 1) {\n const baseViewport = page.getViewport({ scale: 1 });\n emit('pageWidthChange', baseViewport.width);\n }\n\n state.element.innerHTML = '';\n state.element.appendChild(canvas);\n\n // 页码标签\n const label = document.createElement('div');\n label.textContent = String(pageNumber);\n label.style.cssText =\n 'position:absolute;top:8px;right:8px;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);color:white;font-size:12px;padding:4px 12px;border-radius:9999px;';\n state.element.appendChild(label);\n\n state.rendered = true;\n } catch (err: any) {\n if (err?.name !== 'RenderingCancelledException') {\n console.error(`渲染页面 ${pageNumber} 失败:`, err);\n }\n } finally {\n state.rendering = false;\n state.renderTask = null;\n }\n};\n\nconst clearPageCanvas = (pageNumber: number) => {\n const state = pageStates.get(pageNumber);\n if (!state) return;\n\n // 取消正在进行的渲染\n if (state.renderTask) {\n state.renderTask.cancel();\n state.renderTask = null;\n }\n\n // 清理 canvas,保留占位符\n const canvas = state.element.querySelector('canvas');\n if (canvas) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n canvas.remove();\n }\n\n state.element.innerHTML = '';\n state.rendered = false;\n state.rendering = false;\n};\n\nconst initPagePlaceholders = async () => {\n if (!pdfDoc || !containerRef.value) return;\n const wrapper = containerRef.value.querySelector('.pdf-pages') as HTMLDivElement | null;\n if (!wrapper) return;\n\n wrapper.innerHTML = '';\n pageStates.clear();\n\n // 预计算所有页面的高度占位\n for (let i = 1; i <= numPages.value; i++) {\n const pageDiv = document.createElement('div');\n pageDiv.style.cssText = 'position:relative;display:flex;justify-content:center;min-height:800px;';\n pageDiv.dataset.pageNumber = String(i);\n wrapper.appendChild(pageDiv);\n\n pageStates.set(i, {\n element: pageDiv,\n rendered: false,\n rendering: false,\n renderTask: null,\n });\n\n // 使用 IntersectionObserver 监听\n if (observer) {\n observer.observe(pageDiv);\n }\n }\n};\n\nconst loadPdf = async () => {\n error.value = null;\n numPages.value = 0;\n if (pdfDoc) {\n try {\n pdfDoc.destroy();\n } catch {\n // ignore\n }\n pdfDoc = null;\n }\n\n try {\n const loadingTask = pdfjsLib.getDocument({ url: props.url });\n pdfDoc = (await loadingTask.promise) as PdfDocumentProxy;\n numPages.value = pdfDoc.numPages;\n emit('totalPagesChange', pdfDoc.numPages);\n emit('pageChange', 1);\n await nextTick();\n await initPagePlaceholders();\n } catch (err) {\n console.error('PDF 加载错误:', err);\n error.value = t.value('pdf.load_failed');\n }\n};\n\nconst handleScroll = () => {\n if (!containerRef.value || pageStates.size === 0) return;\n\n const container = containerRef.value;\n const scrollTop = container.scrollTop;\n const containerHeight = container.clientHeight;\n const scrollCenter = scrollTop + containerHeight / 2;\n\n let currentVisiblePage = 1;\n let minDistance = Infinity;\n\n pageStates.forEach((state, pageNumber) => {\n const rect = state.element.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const pageCenter = rect.top - containerRect.top + rect.height / 2 + scrollTop;\n const distance = Math.abs(pageCenter - scrollCenter);\n\n if (distance < minDistance) {\n minDistance = distance;\n currentVisiblePage = pageNumber;\n }\n });\n\n if (currentVisiblePage !== props.currentPage) {\n emit('pageChange', currentVisiblePage);\n }\n};\n\nlet zoomDebounceTimer: number | null = null;\nconst handleZoomChange = () => {\n if (zoomDebounceTimer) {\n clearTimeout(zoomDebounceTimer);\n }\n\n zoomDebounceTimer = window.setTimeout(() => {\n // 清理所有已渲染页面\n pageStates.forEach((state, pageNumber) => {\n if (state.rendered) {\n clearPageCanvas(pageNumber);\n }\n });\n\n // 触发 IntersectionObserver 重新渲染可见页面\n if (observer && containerRef.value) {\n const wrapper = containerRef.value.querySelector('.pdf-pages') as HTMLDivElement | null;\n if (wrapper) {\n pageStates.forEach((state) => {\n observer?.unobserve(state.element);\n observer?.observe(state.element);\n });\n }\n }\n }, 150);\n};\n\nonMounted(() => {\n // 初始化 IntersectionObserver,设置缓冲区为上下 500px\n observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n const pageNumber = Number(entry.target.getAttribute('data-page-number'));\n if (!pageNumber) return;\n\n if (entry.isIntersecting) {\n // 页面进入视口,渲染\n renderPage(pageNumber, props.zoom);\n } else {\n // 页面离开视口较远,清理 canvas\n const state = pageStates.get(pageNumber);\n if (state && state.rendered) {\n clearPageCanvas(pageNumber);\n }\n }\n });\n },\n {\n root: containerRef.value,\n rootMargin: '500px 0px',\n threshold: 0,\n }\n );\n\n loadPdf();\n if (containerRef.value) {\n containerRef.value.addEventListener('scroll', handleScroll);\n }\n});\n\nwatch(\n () => props.url,\n (newUrl) => {\n // 只有 URL 有效时才加载(避免空字符串或已 revoke 的 blob URL)\n if (newUrl) {\n loadPdf();\n }\n }\n);\n\nwatch(() => props.zoom, handleZoomChange);\n\nonBeforeUnmount(() => {\n if (zoomDebounceTimer) {\n clearTimeout(zoomDebounceTimer);\n }\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n\n if (containerRef.value) {\n containerRef.value.removeEventListener('scroll', handleScroll);\n }\n\n // 清理所有渲染任务\n pageStates.forEach((state) => {\n if (state.renderTask) {\n state.renderTask.cancel();\n }\n });\n pageStates.clear();\n\n if (pdfDoc) {\n try {\n pdfDoc.destroy();\n } catch {\n // ignore\n }\n pdfDoc = null;\n }\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"vfp-flex vfp-flex-col vfp-items-center vfp-w-full vfp-h-full vfp-overflow-auto vfp-py-4 md:vfp-py-8 vfp-px-2 md:vfp-px-4\"\n >\n <RendererError v-if=\"error\" :message=\"error\" />\n\n <div v-if=\"!error && numPages === 0\" class=\"vfp-flex vfp-items-center vfp-justify-center vfp-min-h-screen\">\n <div\n class=\"vfp-w-12 vfp-h-12 vfp-border-4 vfp-border-line-strong vfp-border-t-spinner-head vfp-rounded-full vfp-animate-spin\"\n />\n </div>\n\n <div v-show=\"!error && numPages > 0\" class=\"pdf-pages vfp-flex vfp-flex-col vfp-gap-4\" />\n\n <div\n v-if=\"numPages > 0\"\n class=\"vfp-sticky vfp-bottom-2 md:vfp-bottom-4 vfp-mt-4 md:vfp-mt-8 vfp-bg-surface-nav-hover vfp-backdrop-blur-xl vfp-text-fg-primary vfp-px-4 vfp-py-2 md:vfp-px-6 md:vfp-py-3 vfp-rounded-full vfp-text-xs md:vfp-text-sm vfp-font-medium vfp-shadow-2xl vfp-border vfp-border-line-weak\"\n >\n 第 {{ currentPage }} 页 / 共 {{ numPages }} 页\n </div>\n </div>\n</template>\n"],"names":["configurePdfWorker","pdfjsLib","props","__props","emit","__emit","t","useTranslator","numPages","ref","error","containerRef","pdfDoc","pageStates","observer","renderPage","pageNumber","scale","state","page","viewport","canvas","ctx","renderTask","baseViewport","label","err","clearPageCanvas","initPagePlaceholders","wrapper","i","pageDiv","loadPdf","nextTick","handleScroll","container","scrollTop","containerHeight","scrollCenter","currentVisiblePage","minDistance","rect","containerRect","pageCenter","distance","zoomDebounceTimer","handleZoomChange","onMounted","entries","entry","watch","newUrl","onBeforeUnmount","_createElementBlock","_createBlock","RendererError","_openBlock","_hoisted_1","_cache","_createElementVNode","_withDirectives","_hoisted_2","_vShow","_hoisted_3","_toDisplayString"],"mappings":"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"}