Skip to content

Commit 7826deb

Browse files
committed
feat: 增加 PDF Reader 组件
1 parent 721f390 commit 7826deb

3 files changed

Lines changed: 120 additions & 45 deletions

File tree

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
11
@namespace BootstrapBlazor.Components
22
@inherits BootstrapModuleComponentBase
33

4-
<div @attributes="@AdditionalAttributes" id="@Id" class="@ClassString">
5-
<div id="viewerContainer">
6-
<div id="viewer" class="pdfViewer"></div>
4+
<div @attributes="@AdditionalAttributes" id="@Id" class="@ClassString" style="@StyleString">
5+
<div class="bb-view-toolbar">
6+
<div class="bb-view-title">
7+
<div class="bb-view-bar"><i class="fa-solid fa-bars"></i></div>
8+
<span class="bb-view-subject">@_docTitle</span>
9+
</div>
10+
<div class="bb-view-pages">
11+
<div>-</div>
12+
<input type="text" class="bb-view-num" /><span class="bb-view-slash">/</span><div>14</div>
13+
<div>+</div>
14+
<div class="bb-view-divider"></div>
15+
<div class="bb-view-fit-page"></div>
16+
<div class="bb-view-fit-width"></div>
17+
<div class="bb-view-fit-rotate"></div>
18+
<div class="bb-view-divider"></div>
19+
<div class="bb-view-draw"></div>
20+
</div>
21+
<div class="bb-view-controls"></div>
22+
</div>
23+
<div class="bb-view-container">
24+
<div class="pdfViewer"></div>
725
</div>
8-
@* <canvas></canvas> *@
926
</div>

src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
// Website: https://www.blazor.zone or https://argozhang.github.io/
44

5+
using Microsoft.AspNetCore.Components;
56

67
namespace BootstrapBlazor.Components;
78

@@ -11,13 +12,69 @@ namespace BootstrapBlazor.Components;
1112
[JSModuleAutoLoader("./_content/BootstrapBlazor.PdfReader/PdfReader.razor.js", JSObjectReference = true)]
1213
public partial class PdfReader
1314
{
15+
/// <summary>
16+
/// 获得/设置 PDF 文档路径
17+
/// </summary>
18+
[Parameter]
19+
public string? Url { get; set; }
20+
21+
/// <summary>
22+
/// 获得/设置 PDF 组件高度 默认 600px
23+
/// </summary>
24+
[Parameter]
25+
public string? ViewHeight { get; set; }
26+
1427
private string? ClassString => CssBuilder.Default("bb-pdf-reader")
1528
.AddClassFromAttributes(AdditionalAttributes)
1629
.Build();
1730

31+
private string? StyleString => CssBuilder.Default()
32+
.AddClass($"--bb-pdf-view-height: {ViewHeight};", !string.IsNullOrEmpty(ViewHeight))
33+
.AddClassFromAttributes(AdditionalAttributes)
34+
.Build();
35+
36+
private string? _docTitle;
37+
1838
/// <summary>
1939
/// <inheritdoc/>
2040
/// </summary>
41+
protected override void OnParametersSet()
42+
{
43+
base.OnParametersSet();
44+
45+
_docTitle = Path.GetFileName(Url);
46+
}
47+
48+
/// <summary>
49+
/// <inheritdoc/>
50+
/// </summary>
51+
/// <returns></returns>
52+
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new { Url });
53+
54+
/// <summary>
55+
/// 跳转到指定页码方法
56+
/// </summary>
57+
/// <param name="pageNumber"></param>
58+
/// <returns></returns>
59+
public Task NavigateToPageAsync(int pageNumber) => InvokeVoidAsync("navigateToPage", Id, pageNumber);
60+
61+
/// <summary>
62+
/// 页面开始初始化时回调方法
63+
/// </summary>
64+
/// <returns></returns>
65+
[JSInvokable]
66+
public Task PagesInit()
67+
{
68+
return Task.CompletedTask;
69+
}
70+
71+
/// <summary>
72+
/// 改变页码时回调方法
73+
/// </summary>
2174
/// <returns></returns>
22-
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop);
75+
[JSInvokable]
76+
public Task PageChanging()
77+
{
78+
return Task.CompletedTask;
79+
}
2380
}

src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
1-
import './pdf.min.mjs'
2-
import './pdf_viewer.mjs'
1+
import './lib/pdf.min.mjs'
2+
import './lib/pdf_viewer.mjs'
33
import { addLink } from '../BootstrapBlazor/modules/utility.js';
4+
import Data from '../BootstrapBlazor/modules/data.js';
45

56
if (pdfjsLib != null) {
67
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdf.worker.min.mjs';
78
}
89

9-
export async function init(id, invoke, scale, rotation, url, password = null) {
10+
export async function init(id, invoke, options) {
1011
const el = document.getElementById(id);
1112
if (el === null) {
1213
return;
1314
}
1415

15-
await addLink('./_content/BootstrapBlazor.PdfReader/pdf_viewer.css');
16-
17-
scale = 1.5;
18-
rotation = 0;
19-
url = './samples/sample.pdf';
16+
await addLink('./_content/BootstrapBlazor.PdfReader/css/pdf.css');
2017

2118
//const elementId = el.querySelector('canvas');
2219
//const pdf = new Pdf(elementId);
2320
//pdf.scale = scale;
2421
//pdf.rotation = rotation;
2522

26-
// prepare loading options (optional password allowed)
27-
const options = { url };
28-
if (password) {
29-
options.password = password; // pre-supply if user already has it
30-
}
31-
32-
// begin loading document
3323
const loadingTask = pdfjsLib.getDocument(options);
3424

25+
loadingTask.onProgress = function (progressData) {
26+
console.log(progressData.loaded, progressData.total);
27+
};
28+
3529
// handle password only when required (optional password support)
3630
loadingTask.onPassword = function (updatePassword, reason) {
3731
if (reason === pdfjsLib.PasswordResponses.NEED_PASSWORD) {
@@ -44,7 +38,7 @@ export async function init(id, invoke, scale, rotation, url, password = null) {
4438
}
4539
};
4640

47-
const container = document.getElementById("viewerContainer");
41+
const container = el.querySelector(".bb-view-container");
4842
const eventBus = new pdfjsViewer.EventBus();
4943
const pdfViewer = new pdfjsViewer.PDFViewer({
5044
container,
@@ -55,39 +49,41 @@ export async function init(id, invoke, scale, rotation, url, password = null) {
5549
eventBus.on("pagesinit", function () {
5650
// We can use pdfViewer now, e.g. let's change default scale.
5751
pdfViewer.currentScaleValue = "page-width";
52+
console.log("pagesInit");
5853
});
5954

6055
// handle the promise
6156
const pdfDocument = await loadingTask.promise;
6257
pdfViewer.setDocument(pdfDocument);
6358

64-
// pdfDocument.then(function (doc) {
65-
// pdf.pdfDoc = doc;
66-
// pdf.pagesCount = doc.numPages;
67-
// renderPage(pdf, pdf.pageNum);
68-
69-
// // notify .NET side that document is loaded
70-
// invoke.invokeMethodAsync('DocumentLoaded', {
71-
// pagesCount: pdf.pagesCount,
72-
// pageNumber: pdf.pageNum
73-
// });
74-
// })
75-
// .catch(function (error) {
76-
// console.error("PDF loading error:", error);
77-
78-
// // handle password exceptions specifically
79-
// if (error.name === "PasswordException") {
80-
// console.error("Password required but not provided");
81-
// }
82-
83-
// // notify .NET side that document loading failed
84-
// invoke.invokeMethodAsync('DocumentLoadError', error.message);
85-
// });
86-
59+
// pdfDocument.then(function (doc) {
60+
// pdf.pdfDoc = doc;
61+
// pdf.pagesCount = doc.numPages;
62+
// renderPage(pdf, pdf.pageNum);
63+
64+
// // notify .NET side that document is loaded
65+
// invoke.invokeMethodAsync('DocumentLoaded', {
66+
// pagesCount: pdf.pagesCount,
67+
// pageNumber: pdf.pageNum
68+
// });
69+
// })
70+
// .catch(function (error) {
71+
// console.error("PDF loading error:", error);
72+
73+
// // handle password exceptions specifically
74+
// if (error.name === "PasswordException") {
75+
// console.error("Password required but not provided");
76+
// }
77+
78+
// // notify .NET side that document loading failed
79+
// invoke.invokeMethodAsync('DocumentLoadError', error.message);
80+
// });
81+
82+
Data.set(id, pdfViewer);
8783
}
8884

8985
export function dispose(id) {
90-
86+
data.remove(id);
9187
}
9288

9389
function getCanvas(item) {
@@ -135,6 +131,11 @@ class Pdf {
135131
}
136132
}
137133

134+
export function navigateToPage(id, pageNumber) {
135+
const pdf = Data.get(id);
136+
pdf.currentPageNumber = pageNumber;
137+
}
138+
138139
export function firstPage(invoke, elementId) {
139140
const pdf = getPdf(elementId);
140141

0 commit comments

Comments
 (0)