From 3ae0766544859f60bbe5b9ac9acfcb932c103e23 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 26 Nov 2025 18:48:48 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20PdfReaderO?= =?UTF-8?q?ptions=20=E9=85=8D=E7=BD=AE=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.PdfReader/PdfReader.razor | 11 +- .../PdfReader.razor.cs | 197 +++++++++++++----- .../PdfReaderOptions.cs | 76 ------- 3 files changed, 155 insertions(+), 129 deletions(-) delete mode 100644 src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor index b4410503..a50b4d9e 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor @@ -3,7 +3,7 @@ @inherits BootstrapModuleComponentBase
- @if (Options.ShowToolbar) + @if (ShowToolbar) {
@@ -23,12 +23,15 @@
-
+ @if (ShowDownload) + { +
+ }
- @if (Options.ShowTwoPagesOnViewButton) + @if (ShowTwoPagesOneViewButton) { @@ -40,7 +43,7 @@
}
- @if (Options.EnableThumbnails) + @if (EnableThumbnails) {
} diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs index fc5e16c1..c7e805ca 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs @@ -14,11 +14,88 @@ namespace BootstrapBlazor.Components; public partial class PdfReader { /// - /// 获得/设置 配置项实例 + /// 获得/设置 是否显示工具栏 默认 true 显示 /// [Parameter] - [NotNull] - public PdfReaderOptions? Options { get; set; } + public bool ShowToolbar { get; set; } = true; + + /// + /// 获得/设置 是否显示下载按钮 默认 true 显示 + /// + [Parameter] + public bool ShowDownload { get; set; } = true; + + /// + /// 获得/设置 是否显示缩略图 默认 true 显示 + /// + [Parameter] + public bool EnableThumbnails { get; set; } = true; + + /// + /// 获得/设置 PDF 文档路径 + /// + [Parameter] + public string? Url { get; set; } + + /// + /// 获得/设置 PDF 组件高度 默认 600px + /// + [Parameter] + public string? ViewHeight { get; set; } + + /// + /// 获得/设置 当前页码 + /// + [Parameter] + public uint CurrentPage { get; set; } + + /// + /// 获得/设置 当前缩放倍率 默认 null 使用 100% + /// + [Parameter] + public string? CurrentScale { get; set; } + + /// + /// 获得/设置 是否适配当前页面宽度 默认 false + /// + [Parameter] + public bool IsFitToPage { get; set; } + + /// + /// 获得/设置 是否显示双页单视图按钮 默认 true 显示 + /// + [Parameter] + public bool ShowTwoPagesOneViewButton { get; set; } = true; + + /// + /// 获得/设置 是否启用双页单视图模式 默认 false + /// + [Parameter] + public bool EnableTwoPagesOneView { get; set; } + + /// + /// 页面初始化回调方法 + /// + [Parameter] + public Func? OnPagesInitAsync { get; set; } + + /// + /// 页面加载完毕回调方法 + /// + [Parameter] + public Func? OnPagesLoadedAsync { get; set; } + + /// + /// 页面初始化回调方法 + /// + [Parameter] + public Func? OnPageChangedAsync { get; set; } + + /// + /// 设置双页单视图模式回调方法 + /// + [Parameter] + public Func? OnTwoPagesOneViewAsync { get; set; } /// /// 获得/设置 更多按钮图标 默认为 null 使用内置图标 @@ -26,17 +103,26 @@ public partial class PdfReader [Parameter] public string? MoreButtonIcon { get; set; } + /// + /// 点击下载按钮回调方法 默认 null 使用组件内置下载功能 + /// + [Parameter] + public Func? OnDownloadAsync { get; set; } + + [Inject, NotNull] + private DownloadService? DownloadService { get; set; } + private string? ClassString => CssBuilder.Default("bb-pdf-reader") .AddClassFromAttributes(AdditionalAttributes) .Build(); private string? StyleString => CssBuilder.Default() - .AddClass($"--bb-pdf-view-height: {Options.ViewHeight};", !string.IsNullOrEmpty(Options.ViewHeight)) + .AddClass($"--bb-pdf-view-height: {ViewHeight};", !string.IsNullOrEmpty(ViewHeight)) .AddClassFromAttributes(AdditionalAttributes) .Build(); private string? ViewBodyString => CssBuilder.Default("bb-view-body") - .AddClass("fit-page", Options.IsFitToPage) + .AddClass("fit-page", IsFitToPage) .Build(); private string? _docTitle; @@ -45,13 +131,14 @@ public partial class PdfReader private string? _url; private string? _currentScale; private bool _enableTwoPagesOneView; + private bool _showTwoPagesOneViewButton; private string? _twoPagesOneViewIcon; private readonly HashSet AllowedScaleValues = ["page-actual", "page-width", "page-height", "page-fit", "auto"]; private string CurrentPageString { - get => Options.CurrentPage.ToString(CultureInfo.InvariantCulture); + get => CurrentPage.ToString(CultureInfo.InvariantCulture); set => SetCurrentPage(value); } @@ -59,13 +146,13 @@ private void SetCurrentPage(string value) { if (uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var num)) { - Options.CurrentPage = num; + CurrentPage = num; } } private string CurrentScaleString { - get => $"{Options.CurrentScale ?? "100"}%"; + get => $"{CurrentScale ?? "100"}%"; set => SetCurrentScale(value); } @@ -73,7 +160,7 @@ private void SetCurrentScale(string value) { if (string.IsNullOrEmpty(value)) { - Options.CurrentScale = "100"; + CurrentScale = "100"; } else if (float.TryParse(value.TrimEnd("%"), out var v)) { @@ -84,14 +171,14 @@ private void SetCurrentScale(string value) _ => v }; - Options.CurrentScale = v.ToString(CultureInfo.InvariantCulture); + CurrentScale = v.ToString(CultureInfo.InvariantCulture); } } private void OnToggleTwoPagesOneView() { _enableTwoPagesOneView = !_enableTwoPagesOneView; - Options.EnableTwoPagesOnView = _enableTwoPagesOneView; + EnableTwoPagesOneView = _enableTwoPagesOneView; _twoPagesOneViewIcon = _enableTwoPagesOneView ? "fa-solid fa-fw fa-check" : "fa-solid fa-fw"; } @@ -103,16 +190,14 @@ protected override void OnParametersSet() { base.OnParametersSet(); - Options ??= new PdfReaderOptions(); + MoreButtonIcon ??= "fa-solid fa-ellipsis-vertical"; + _twoPagesOneViewIcon ??= "fa-solid fa-fw"; - if (Options.CurrentPage == 0) + if (CurrentPage == 0) { - Options.CurrentPage = 1; + CurrentPage = 1; } - _docTitle = Path.GetFileName(Options.Url); - - MoreButtonIcon ??= "fa-solid fa-ellipsis-vertical"; - _twoPagesOneViewIcon ??= "fa-solid fa-fw"; + _docTitle = Path.GetFileName(Url); } /// @@ -126,37 +211,43 @@ protected override async Task OnAfterRenderAsync(bool firstRender) if (firstRender) { - _isFitToPage = Options.IsFitToPage; - _currentPage = Options.CurrentPage; - _url = Options.Url; - _currentScale = Options.CurrentScale; - _enableTwoPagesOneView = Options.EnableTwoPagesOnView; + _isFitToPage = IsFitToPage; + _currentPage = CurrentPage; + _url = Url; + _currentScale = CurrentScale; + _enableTwoPagesOneView = EnableTwoPagesOneView; + _showTwoPagesOneViewButton = ShowTwoPagesOneViewButton; } - if (_url != Options.Url) + if (_url != Url) { - _url = Options.Url; + _url = Url; await InvokeInitAsync(); } - if (_isFitToPage != Options.IsFitToPage) + if (_isFitToPage != IsFitToPage) { - _isFitToPage = Options.IsFitToPage; + _isFitToPage = IsFitToPage; await TriggerFit(_isFitToPage ? "fitToPage" : "fitToWidth"); } - if (_currentPage != Options.CurrentPage) + if (_currentPage != CurrentPage) { - _currentPage = Options.CurrentPage; + _currentPage = CurrentPage; await NavigateToPageAsync(_currentPage); } - if (_currentScale != Options.CurrentScale) + if (_currentScale != CurrentScale) { - _currentScale = Options.CurrentScale; + _currentScale = CurrentScale; await InvokeVoidAsync("scale", Id, _currentScale); } - if (_enableTwoPagesOneView != Options.EnableTwoPagesOnView) + if (_enableTwoPagesOneView != EnableTwoPagesOneView) { - _currentScale = Options.CurrentScale; + _enableTwoPagesOneView = EnableTwoPagesOneView; + await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView); + } + if (_showTwoPagesOneViewButton != ShowTwoPagesOneViewButton) + { + _showTwoPagesOneViewButton = ShowTwoPagesOneViewButton; await InvokeVoidAsync("setPages", Id, _enableTwoPagesOneView); } } @@ -167,13 +258,13 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new { - Options.Url, - Options.IsFitToPage, - Options.EnableThumbnails, - TriggerPagesInit = Options.OnPagesInitAsync != null, - TriggerPagesLoaded = Options.OnPagesLoadedAsync != null, - TriggerPageChanged = Options.OnPageChangedAsync != null, - TriggerTowPagesOnViewChanged = Options.OnTwoPagesOneViewAsync != null + Url, + IsFitToPage, + EnableThumbnails, + TriggerPagesInit = OnPagesInitAsync != null, + TriggerPagesLoaded = OnPagesLoadedAsync != null, + TriggerPageChanged = OnPageChangedAsync != null, + TriggerTowPagesOnViewChanged = OnTwoPagesOneViewAsync != null }); /// @@ -186,12 +277,12 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// /// 适应页面宽度 /// - public void FitToPage() => Options.IsFitToPage = true; + public void FitToPage() => IsFitToPage = true; /// /// 适应文档宽度 /// - public void FitToWidth() => Options.IsFitToPage = false; + public void FitToWidth() => IsFitToPage = false; /// /// 旋转页面方法 @@ -211,6 +302,14 @@ public async Task RotateRight() await InvokeVoidAsync("rotate", Id, 90); } + private async Task OnDownload() + { + if (OnDownloadAsync != null) + { + await OnDownloadAsync(); + } + } + private Task TriggerFit(string methodName) => InvokeVoidAsync(methodName, Id); /// @@ -220,9 +319,9 @@ public async Task RotateRight() [JSInvokable] public async Task PagesInit(int pagesCount) { - if (Options.OnPagesInitAsync != null) + if (OnPagesInitAsync != null) { - await Options.OnPagesInitAsync(pagesCount); + await OnPagesInitAsync(pagesCount); } } @@ -233,9 +332,9 @@ public async Task PagesInit(int pagesCount) [JSInvokable] public async Task PagesLoaded(int pagesCount) { - if (Options.OnPagesLoadedAsync != null) + if (OnPagesLoadedAsync != null) { - await Options.OnPagesLoadedAsync(pagesCount); + await OnPagesLoadedAsync(pagesCount); } } @@ -247,11 +346,11 @@ public async Task PagesLoaded(int pagesCount) public async Task PageChanged(uint pageIndex) { _currentPage = pageIndex; - Options.CurrentPage = pageIndex; + CurrentPage = pageIndex; - if (Options.OnPageChangedAsync != null) + if (OnPageChangedAsync != null) { - await Options.OnPageChangedAsync(pageIndex); + await OnPageChangedAsync(pageIndex); } } } diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs b/src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs deleted file mode 100644 index e553eea0..00000000 --- a/src/components/BootstrapBlazor.PdfReader/PdfReaderOptions.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// Website: https://www.blazor.zone or https://argozhang.github.io/ - -namespace BootstrapBlazor.Components; - -/// -/// PdfReader 组件配置类 -/// -public class PdfReaderOptions -{ - /// - /// 获得/设置 是否显示工具栏 默认 true 显示 - /// - public bool ShowToolbar { get; set; } = true; - - /// - /// 获得/设置 是否显示缩略图 默认 true 显示 - /// - public bool EnableThumbnails { get; set; } = true; - - /// - /// 获得/设置 PDF 文档路径 - /// - public string? Url { get; set; } - - /// - /// 获得/设置 PDF 组件高度 默认 600px - /// - public string? ViewHeight { get; set; } - - /// - /// 获得/设置 当前页码 - /// - public uint CurrentPage { get; set; } - - /// - /// 获得/设置 当前缩放倍率 默认 null 使用 100% - /// - public string? CurrentScale { get; set; } - - /// - /// 获得/设置 是否适配当前页面宽度 默认 false - /// - public bool IsFitToPage { get; set; } - - /// - /// 获得/设置 是否显示双页单视图按钮 默认 true 显示 - /// - public bool ShowTwoPagesOnViewButton { get; set; } = true; - - /// - /// 获得/设置 是否启用双页单视图模式 默认 false - /// - public bool EnableTwoPagesOnView { get; set; } - - /// - /// 页面初始化回调方法 - /// - public Func? OnPagesInitAsync { get; set; } - - /// - /// 页面加载完毕回调方法 - /// - public Func? OnPagesLoadedAsync { get; set; } - - /// - /// 页面初始化回调方法 - /// - public Func? OnPageChangedAsync { get; set; } - - /// - /// 设置双页单视图模式回调方法 - /// - public Func? OnTwoPagesOneViewAsync { get; set; } -} From fb8dd4a455f75a14014fd184f44c0f255106edae Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 26 Nov 2025 18:49:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20resetTwoPagesO?= =?UTF-8?q?neView=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PdfReader.razor.js | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js index 3a1eebf1..119f8205 100644 --- a/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js +++ b/src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js @@ -88,16 +88,32 @@ export function scale(id, scale) { } } -export function setPages(id, enableTowPagesOnView) { +export function setPages(id, enableTwoPagesOneView) { const { el, pdfViewer } = Data.get(id); if (pdfViewer) { - if (enableTowPagesOnView) { + if (enableTwoPagesOneView) { pdfViewer.spreadMode = 1; } else { pdfViewer.spreadMode = 0; } } + + resetTwoPagesOneView(el, pdfViewer); +} + +const resetTwoPagesOneView = (el, pdfViewer) => { + const twoPagesOneView = el.querySelector(".dropdown-item-pages"); + if (twoPagesOneView) { + EventHandler.on(twoPagesOneView, "click", e => { + if (pdfViewer.spreadMode === 0) { + pdfViewer.spreadMode = 1; + } + else { + pdfViewer.spreadMode = 0; + } + }); + } } const addEventListener = (el, pdfViewer, eventBus, invoke, options) => { @@ -185,17 +201,7 @@ const addEventListener = (el, pdfViewer, eventBus, invoke, options) => { EventHandler.on(minus, "click", e => updateScale(pdfViewer, e.target, -1)); EventHandler.on(plus, "click", e => updateScale(pdfViewer, e.target, 1)); - const towPagesOneView = el.querySelector(".dropdown-item-pages"); - if (towPagesOneView) { - EventHandler.on(towPagesOneView, "click", e => { - if (pdfViewer.spreadMode === 0) { - pdfViewer.spreadMode = 1; - } - else { - pdfViewer.spreadMode = 0; - } - }); - } + resetTwoPagesOneView(el, pdfViewer); const thumbnailsToggle = el.querySelector(".bb-view-bar"); if (thumbnailsToggle) {