From 4aa85dbf7bdc8ce83cc900109c47b3450f6c8b12 Mon Sep 17 00:00:00 2001 From: cwchen <1048842385@qq.com> Date: Fri, 28 Nov 2025 10:02:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96pdf=20=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/common/DocumentSearch.vue | 41 +++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/views/common/DocumentSearch.vue b/src/views/common/DocumentSearch.vue index 0185563..484a746 100644 --- a/src/views/common/DocumentSearch.vue +++ b/src/views/common/DocumentSearch.vue @@ -73,7 +73,7 @@ if (resolvedWorkerSrc) { pdfjsLib.GlobalWorkerOptions.workerSrc = null } -const DEFAULT_SCALE = 1.1 +const DEFAULT_SCALE = 1 const DEFAULT_PDF_URL = 'http://192.168.0.14:9090/smart-bid/technicalSolutionDatabase/2025/10/30/fe5b46ea37554516a71e7c0c486d3715.pdf' export default { @@ -268,6 +268,16 @@ export default { this.isPrefetching = false this.initialPreloadedCount = 0 + // 预先获取第一页的 viewport,用于设置所有容器的初始尺寸 + let defaultViewport = null + try { + const firstPage = await this.pdfDoc.getPage(1) + defaultViewport = firstPage.getViewport({ scale: this.scale }) + this.pageCache.set(1, firstPage) + } catch (error) { + console.warn('获取第一页 viewport 失败', error) + } + const fragment = document.createDocumentFragment() for (let pageNumber = 1; pageNumber <= this.totalPages; pageNumber += 1) { const placeholder = document.createElement('div') @@ -276,10 +286,24 @@ export default { placeholder.style.position = 'relative'; placeholder.dataset.page = pageNumber placeholder.dataset.status = 'placeholder' + + // 如果获取到了默认 viewport,预先设置容器尺寸,避免滚动时修改 + if (defaultViewport) { + placeholder.style.width = `${defaultViewport.width}px` + placeholder.style.height = `${defaultViewport.height}px` + placeholder.style.backgroundColor = '#fff' + } + fragment.appendChild(placeholder) this.pageContainers.push(placeholder) } container.appendChild(fragment) + + // 设置 wrapper 的最小宽度 + if (defaultViewport && this.$refs.pdfWrapper) { + this.$refs.pdfWrapper.style.minWidth = `${Math.ceil(defaultViewport.width)}px` + } + container.scrollTop = 0 this.setupIntersectionObserver() @@ -289,11 +313,17 @@ export default { this.isDocumentReady = true }, - ensureContainerDimensions(pageNumber, viewport) { + ensureContainerDimensions(pageNumber, viewport, force = false) { const index = pageNumber - 1 const container = this.pageContainers[index] if (!container) return + // 如果容器已经有尺寸且不是强制更新,则跳过,避免滚动时修改尺寸导致滚动位置跳动 + const hasDimensions = container.style.width && container.style.height && container.style.width !== '0px' && container.style.height !== '0px' + if (hasDimensions && !force && container.dataset.status !== 'placeholder') { + return + } + container.style.width = `${viewport.width}px` container.style.height = `${viewport.height}px` container.style.margin = '0px auto 10px' @@ -330,7 +360,8 @@ export default { if (!container) return null const viewport = page.getViewport({ scale: this.scale }) - this.ensureContainerDimensions(pageNumber, viewport) + // 渲染时允许更新尺寸(如果 viewport 与预设不同) + this.ensureContainerDimensions(pageNumber, viewport, true) container.classList.add('is-loading') const oldCanvas = container.querySelector('.pdf-canvas') @@ -497,8 +528,8 @@ export default { try { const page = await this.pdfDoc.getPage(pageNumber) this.pageCache.set(pageNumber, page) - const viewport = page.getViewport({ scale: this.scale }) - this.ensureContainerDimensions(pageNumber, viewport) + // 预取时只缓存页面对象,不修改容器尺寸,避免滚动时影响滚动位置 + // 容器尺寸会在实际渲染时通过 ensureContainerDimensions 设置 } catch (error) { console.warn(`预取第 ${pageNumber} 页失败`, error) }