From 550c547b71fd4a2d2f37126e6fcd1f74154ab704 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 28 Nov 2025 16:43:18 +0800 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=20worker=20?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js index 66951070..6cdb1b14 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js @@ -5,7 +5,7 @@ import Data from '../BootstrapBlazor/modules/data.js'; import EventHandler from '../BootstrapBlazor/modules/event-handler.js'; if (pdfjsLib != null) { - pdfjsLib.GlobalWorkerOptions.workerSrc = './pdf.worker.min.mjs'; + pdfjsLib.GlobalWorkerOptions.workerSrc = '/_content/BootstrapBlazor.PdfReader/lib/pdf.worker.min.mjs'; } export async function init(id, invoke, options) { From 7f96aecdfd6f4745d129dfcbf79c273ffee0ad7e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Fri, 28 Nov 2025 22:25:39 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20document=20?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.PdfReader/PdfReader.razor | 75 ++++++++++- .../PdfReader.razor.css | 40 ++++++ .../PdfReader.razor.js | 117 +++++++++++++++++- 3 files changed, 228 insertions(+), 4 deletions(-) diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor index 6de2cc4b..2a27ba14 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor @@ -74,7 +74,9 @@ } @if (ShowTwoPagesOneView || ShowPresentationMode) { - +
+
+
} +
+
+
+
Document properties
+
+
File name:
+
+
+
+
File size:
+
+
+
+
+
+
+
Title:
+
+
+
+
Author:
+
+
+
+
Subject:
+
+
+
+
Keywords:
+
+
+
+
Created:
+
+
+
+
Modified:
+
+
+
+
Application:
+
+
+
+
+
+
+
PDF producer:
+
+
+
+
PDF version:
+
+
+
+
Page count:
+
+
+
+
Page size:
+
+
+
+
+
+
+
Fast web view:
+
No
+
+
+
diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css index 7a9b3cd0..24cff0f7 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css @@ -209,3 +209,43 @@ background-color: #000; inset: 0; } + +.bb-view-pdf-info { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + +} + +.bb-view-pdf-backdrop { + position: absolute; + inset: 0; + background-color: #000; + opacity: 0.6; + z-index: 1; +} + +.bb-view-pdf-dialog { + background-color: #fff; + padding: 1rem; + z-index: 5; + border-radius: var(--bs-border-radius); +} + +.bb-view-pdf-dialog-item { + display: flex; + flex-wrap: nowrap; + width: 344px; +} + +.bb-view-pdf-dialog-item:not(:last-child) { + margin-block-start: .5rem; +} + +.bb-view-pdf-dialog-label { + width: 108px; + white-space: nowrap; + overflow: hidden; +} diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js index 6cdb1b14..aad0e057 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js @@ -101,9 +101,120 @@ const loadPdf = async (el, invoke, options) => { const pdfDocument = await loadingTask.promise; pdfViewer.setDocument(pdfDocument); + pdfDocument.getMetadata().then(metadata => { + loadMetadata(el, pdfViewer, metadata); + }); + return pdfViewer; } +const loadMetadata = (el, pdfViewer, metadata) => { + console.log(metadata); + + const filename = el.querySelector('.bb-view-pdf-dialog-filename'); + const docTitle = el.querySelector('.bb-view-subject'); + filename.textContent = docTitle.textContent; + + const filesize = el.querySelector('.bb-view-pdf-dialog-filesize'); + filesize.textContent = getFilesize(metadata); + + const title = el.querySelector('.bb-view-pdf-dialog-title'); + const author = el.querySelector('.bb-view-pdf-dialog-author'); + const subject = el.querySelector('.bb-view-pdf-dialog-subject'); + const keywords = el.querySelector('.bb-view-pdf-dialog-keywords'); + const created = el.querySelector('.bb-view-pdf-dialog-created'); + created.textContent = parsePdfDate(metadata.info.CreationDate)?.toLocaleString(); + + const modified = el.querySelector('.bb-view-pdf-dialog-modified'); + + const application = el.querySelector('.bb-view-pdf-dialog-application'); + application.textContent = metadata.info.Creator; + + const producer = el.querySelector('.bb-view-pdf-dialog-producer'); + producer.textContent = metadata.info.Producer; + + const version = el.querySelector('.bb-view-pdf-dialog-version'); + version.textContent = metadata.info.PDFFormatVersion; + + const count = el.querySelector('.bb-view-pdf-dialog-count'); + count.textContent = pdfViewer.pagesCount; + + const size = el.querySelector('.bb-view-pdf-dialog-size'); + pdfViewer.pdfDocument.getPage(pdfViewer.currentPageNumber).then(page => { + const viewport = page.getViewport({scale: 1}); + size.textContent = `${(viewport.width / 72).toFixed(2)} * ${(viewport.height / 72).toFixed(2)} in (portrait)`; + }); + + const webview = el.querySelector('.bb-view-pdf-dialog-webview'); +} + +function parsePdfDate(pdfDateString) { + if (!pdfDateString || typeof pdfDateString !== 'string') { + return null; + } + + let dateStr = pdfDateString.startsWith('D:') ? pdfDateString.substring(2) : pdfDateString; + + const pdfDateRegex = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})([Zz+-])(\d{2})'?(\d{2})'?$/; + const match = dateStr.match(pdfDateRegex); + + if (!match) { + return null; + } + + const [, year, month, day, hours, minutes, seconds, timezoneSign, timezoneHours, timezoneMinutes ] = match; + + const date = new Date( + parseInt(year), + parseInt(month) - 1, + parseInt(day), + parseInt(hours), + parseInt(minutes), + parseInt(seconds) + ); + + if (timezoneSign === 'Z' || timezoneSign === 'z') { + const utcTime = Date.UTC( + parseInt(year), + parseInt(month) - 1, + parseInt(day), + parseInt(hours), + parseInt(minutes), + parseInt(seconds) + ); + date.setTime(utcTime); + } + else if (timezoneSign === '+' || timezoneSign === '-') { + const offsetHours = parseInt(timezoneHours); + const offsetMinutes = parseInt(timezoneMinutes || 0); + const totalOffsetMinutes = offsetHours * 60 + offsetMinutes; + + if (timezoneSign === '+') { + date.setMinutes(date.getMinutes() - totalOffsetMinutes); + } + else { + date.setMinutes(date.getMinutes() + totalOffsetMinutes); + } + } + return date; +} + +const getFilesize = metadata => { + const length = metadata.contentLength; + if (length < 1024) { + return `${Math.round(length)}B`; + } + else if (length < 1024 * 1024) { + return `${Math.round(length / 1024)}KB`; + } + else if (length < 1024 * 1024 * 1024) { + return `${length / 1024 / 1024}MB`; + } + else if (length < 1024 * 1024 * 1024 * 1024) { + return `${length / 1024 / 1024 / 1024}GB`; + } +} + const setObserver = el => { const observer = new ResizeObserver(entries => { relayoutToolbar(el); @@ -402,7 +513,7 @@ const updateScaleValue = (el, value) => { const scaleEl = el.querySelector(".bb-view-scale-input"); const scale = value * 100; - scaleEl.value = `${Math.round(scale, 0)}%`; + scaleEl.value = `${Math.round(scale)}%`; if (scale === 25) { minus.classList.add("disabled"); @@ -422,7 +533,7 @@ const updateScale = (pdfViewer, button, rate) => { } const scale = pdfViewer.currentScale; - const current = Math.round(parseFloat(scale * 100), 0); + const current = Math.round(parseFloat(scale * 100)); const step = [25, 33, 50, 67, 75, 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, 500]; const findValues = step.filter(s => rate > 0 ? current < s : current > s); if (findValues.length === 0) { @@ -462,7 +573,7 @@ const printPdf = url => { } iframe = document.createElement("iframe"); - iframe.classList = "bb-view-print-iframe"; + iframe.classList.add("bb-view-print-iframe"); iframe.style.position = "fixed"; iframe.style.right = "100%"; iframe.style.bottom = "100%"; From a5dd84cab4472d8189f4e018da91686e35daddde Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 29 Nov 2025 10:18:41 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E6=8C=89=E9=92=AE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.PdfReader/Locales/en.json | 3 ++- .../BootstrapBlazor.PdfReader/Locales/zh.json | 3 ++- .../BootstrapBlazor.PdfReader/PdfReader.razor | 5 +++++ .../PdfReader.razor.css | 21 +++++++++++++++---- .../PdfReader.razor.js | 10 +++++++-- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/components/BootstrapBlazor.PdfReader/Locales/en.json b/src/components/BootstrapBlazor.PdfReader/Locales/en.json index 2208ad32..da66418c 100644 --- a/src/components/BootstrapBlazor.PdfReader/Locales/en.json +++ b/src/components/BootstrapBlazor.PdfReader/Locales/en.json @@ -12,6 +12,7 @@ "Print": "Print", "TwoPageView": "Two pages on view", "PresentationMode": "Presentation mode", - "DocumentProperty": "Document properties" + "DocumentProperty": "Document properties", + "CloseButtonText": "Close" } } diff --git a/src/components/BootstrapBlazor.PdfReader/Locales/zh.json b/src/components/BootstrapBlazor.PdfReader/Locales/zh.json index bb62b23f..d2b90f80 100644 --- a/src/components/BootstrapBlazor.PdfReader/Locales/zh.json +++ b/src/components/BootstrapBlazor.PdfReader/Locales/zh.json @@ -12,6 +12,7 @@ "Print": "打印", "TwoPageView": "双页视图", "PresentationMode": "演示模式", - "DocumentProperty": "文档属性" + "DocumentProperty": "文档属性", + "CloseButtonText": "关闭" } } diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor index 2a27ba14..cf024666 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor @@ -167,6 +167,11 @@
Fast web view:
No
+
+ +
diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css index 24cff0f7..ff2479c8 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css @@ -216,9 +216,13 @@ display: flex; align-items: center; justify-content: center; - + z-index: 5; } + .bb-view-pdf-info:not(.show) { + display: none; + } + .bb-view-pdf-backdrop { position: absolute; inset: 0; @@ -240,12 +244,21 @@ width: 344px; } -.bb-view-pdf-dialog-item:not(:last-child) { - margin-block-start: .5rem; -} + .bb-view-pdf-dialog-item:not(:last-child) { + margin-block-start: .5rem; + } .bb-view-pdf-dialog-label { width: 108px; white-space: nowrap; overflow: hidden; } + +.bb-view-pdf-dialog-close { + text-align: right; + padding-block-start: 1rem; +} + + .bb-view-pdf-dialog-close .btn { + --bs-btn-padding-x: 1rem; + } diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js index aad0e057..89fce61d 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js @@ -141,7 +141,7 @@ const loadMetadata = (el, pdfViewer, metadata) => { const size = el.querySelector('.bb-view-pdf-dialog-size'); pdfViewer.pdfDocument.getPage(pdfViewer.currentPageNumber).then(page => { - const viewport = page.getViewport({scale: 1}); + const viewport = page.getViewport({ scale: 1 }); size.textContent = `${(viewport.width / 72).toFixed(2)} * ${(viewport.height / 72).toFixed(2)} in (portrait)`; }); @@ -162,7 +162,7 @@ function parsePdfDate(pdfDateString) { return null; } - const [, year, month, day, hours, minutes, seconds, timezoneSign, timezoneHours, timezoneMinutes ] = match; + const [, year, month, day, hours, minutes, seconds, timezoneSign, timezoneHours, timezoneMinutes] = match; const date = new Date( parseInt(year), @@ -436,6 +436,12 @@ const addToolbarEventHandlers = (el, pdfViewer, invoke, options) => { // el.requestFullscreen(); //} }); + EventHandler.on(toolbar, "click", ".dropdown-item-doc", e => { + const dialog = el.querySelector(".bb-view-pdf-info"); + if (dialog) { + dialog.classList.add("show"); + } + }); } const resetToolbarView = (el, pdfViewer) => { From 4b21cf8cec5b2e3387ce67183b4437828e4a949a Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 29 Nov 2025 10:33:56 +0800 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E6=96=87=E6=A1=A3=E5=B1=9E=E6=80=A7=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.PdfReader/PdfReader.razor | 2 +- .../BootstrapBlazor.PdfReader/PdfReader.razor.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor index cf024666..268b3657 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor @@ -168,7 +168,7 @@
No
-
diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js index 89fce61d..5af82679 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js @@ -442,6 +442,14 @@ const addToolbarEventHandlers = (el, pdfViewer, invoke, options) => { dialog.classList.add("show"); } }); + + const closeButton = el.querySelector(".btn-close-doc"); + EventHandler.on(closeButton, 'click', e => { + const dialog = el.querySelector(".bb-view-pdf-info"); + if (dialog) { + dialog.classList.remove("show"); + } + }); } const resetToolbarView = (el, pdfViewer) => { @@ -623,5 +631,10 @@ export function dispose(id) { if (iframe) { iframe.remove(); } + + const closeButton = el.querySelector(".btn-close-doc"); + if (closeButton) { + EventHandler.off(closeButton, "click"); + } } } From 6e98feae8a61983143d93ead8c1d32f282609c98 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 29 Nov 2025 10:34:08 +0800 Subject: [PATCH 5/5] chore: bump version 10.0.7 --- .../BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj b/src/components/BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj index fd5f4897..d7c1e685 100644 --- a/src/components/BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj +++ b/src/components/BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj @@ -1,7 +1,7 @@  - 10.0.6 + 10.0.7