diff --git a/Demo.Wasm/Pages/BarcodeReaderPage.razor b/Demo.Wasm/Pages/BarcodeReaderPage.razor
deleted file mode 100644
index 90ae217..0000000
--- a/Demo.Wasm/Pages/BarcodeReaderPage.razor
+++ /dev/null
@@ -1,347 +0,0 @@
-@page "/BarcodeReader"
-
-
条码扫描 BarcodeReader
-
-条码,QR码,Pdf417
-
- { BarCode = string.Empty; ShowScanBarcode = !ShowScanBarcode; })">
- [扫码]
-
-
-
-只解码 Pdf417 格式
-
-
-
-连续解码
-
-
-
-解码所有编码形式 (+ PDF_417 / DATA_MATRIX...)
-
-
-@if (Pdf417 | DecodeAllFormats)
-{
- Result:
-
- @BarCode
-}
-else if (DecodeContinuously)
-{
- DecodeContinuously:
-
- @BarCode
-}
-else
-{
-
-}
-
-@if (ShowScanBarcode)
-{
-
-
-}
-
-
- ShowCodes = !ShowCodes)">
- Code
-
-
-@if (ShowCodes)
-{
-
-
- @@if (ShowScanBarcode)
- {
-
- <BarcodeReader ScanResult="((e) => { BarCode=e; ShowScanBarcode = !ShowScanBarcode; })"
- Close="(()=>ShowScanBarcode=!ShowScanBarcode)"
- OnError="OnError" />
- @@code{
- bool ShowScanBarcode { get; set; } = false;
-
- public string? BarCode { get; set; }
-
- private string message;
-
- private Task OnError(string message)
- {
- this.message = message;
- StateHasChanged();
- return Task.CompletedTask;
- }
-
- }
- }
-
-
-}
-
-
- ShowScanBarcodeCustom = !ShowScanBarcodeCustom)">
- 扫码[自定义界面]
-
-
-
-@if (ShowScanBarcodeCustom)
-{
-
-
-
-
-
扫描
-
重置
-
Close
-
-
- 选择设备:
-
-
-
-
-
-
-
-
-
-
-}
-@message
-
-
-
-
-
-
-
-
事件 Events
-
-
-
-
-
-
- ScanResult
- 扫码结果回调方法/Scan result callback method
- EventCallback<string>
-
-
- Close
- 关闭扫码框回调方法/Close scan code callback method
- EventCallback
-
-
- ScanBtnTitle
- 扫码按钮文本/Scan button title
- Parameter
-
-
- ResetBtnTitle
- 复位按钮文本/Reset button title
- Parameter
-
-
- CloseBtnTitle
- 关闭按钮文本/Close button title
- Parameter
-
-
- Pdf417
- 只解码 Pdf417 格式
- Parameter
-
-
- Decodeonce
- 单次|连续解码,默认单次
- Parameter
-
-
- DecodeAllFormats
- 解码所有编码形式,性能较差, 开启后可用 options.formats 指定编码形式.默认为 false
- Parameter
-
-
- options
- ZXingOptions 选项: Pdf417 | Decodeonce | TimeBetweenDecodingAttempts | DecodeAllFormats | formats
- Parameter
-
-
- SelectDeviceBtnTitle
- 选择设备按钮文本
- Parameter
-
-
- OnError
- 错误信息回调
- Func<string, Task>
-
-
- UseBuiltinDiv
- 使用内置扫码界面,默认True
- bool
-
-
-
-
- 参数/Parameter
- 说明/Description
- 类型/Type
-
-
-
-
-
-
-
-
-
-
-
-
-
-
条码格式 BarcodeFormat
-
-
-
-
- 1D product
- 1D industrial
- 2D
-
-
-
-
- UPC-A
- Code 39
- QR Code
-
-
- UPC-E
- Code 93
- Data Matrix
-
-
- EAN-8
- Code 128
- Aztec
-
-
- EAN-13
- Codabar
- PDF 417
-
-
-
- ITF
- MaxiCode
-
-
-
- RSS-14
-
-
-
-
- RSS-Expanded *
-
-
-
-
-
-
-@ver
-@build
-
-@code{
-
- ///
- /// 显示扫码界面
- ///
- bool ShowScanBarcode { get; set; } = false;
-
- ///
- /// 条码
- ///
- public string? BarCode { get; set; }
-
- public bool Pdf417 { get; set; }
- public bool DecodeContinuously { get; set; }
- public bool DecodeAllFormats { get; set; }
-
- private string message;
-
- private Task OnError(string message)
- {
- this.message = message;
- StateHasChanged();
- return Task.CompletedTask;
- }
-
- bool ShowCodes;
-
- private void ScanResult(string e)
- {
- if (!DecodeContinuously)
- {
- BarCode = e;
- ShowScanBarcode = !ShowScanBarcode;
- }
- else
- {
- if (BarCode.Length > 60) BarCode = "";
- BarCode += e + Environment.NewLine;
- }
- }
-
- #region Custom
-
- ///
- /// 显示扫码界面Custom
- ///
- bool ShowScanBarcodeCustom { get; set; } = false;
-
- ///
- /// 条码
- ///
- public string? BarCodeCustom { get; set; }
-
- BarcodeReader barcodeReaderCustom;
-
- #endregion
-
-
- string? ver { get; set; }
- string? build { get; set; }
-
-
- Version? version { get; set; } = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
-
- protected override async Task OnInitializedAsync()
- {
- await base.OnInitializedAsync();
-
- ver = $"Ver {version?.Major}.{version?.Minor}.{version?.Build}";
- build = "Build:" + File.GetLastWriteTime(Path.Combine(Directory.GetCurrentDirectory(), "Demo.Server.dll")).ToLocalTime().ToString("yyyy-MM-dd HH:mm");
-
- }
-}
diff --git a/Demo.Wasm/Pages/HandwrittenPage.razor b/Demo.Wasm/Pages/HandwrittenPage.razor
deleted file mode 100644
index e39c1e6..0000000
--- a/Demo.Wasm/Pages/HandwrittenPage.razor
+++ /dev/null
@@ -1,109 +0,0 @@
-@page "/handwritten"
-
-Handwritten 手写签名
-
- ShowHandwritten = !ShowHandwritten)">
- [签名]
-
-
-@if (ShowHandwritten)
-{
-
-
-
-}
-
-
-
-
事件 Events
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- HandwrittenBase64
- 签名结果回调方法
- EventCallback<string>
-
-
-
-
-
-
-
-
- Close
- 关闭签名框回调方法
- EventCallback
-
-
-
-
-
-
-
-
-
- 参数
- 说明
- 类型
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@code{
-
- ///
- /// 显示签名界面
- ///
- bool ShowHandwritten { get; set; } = false;
-
- ///
- /// 签名Base64
- ///
- public string? DrawBase64 { get; set; }
-
-
-
-}
\ No newline at end of file
diff --git a/Demo.Wasm/Pages/Index.razor b/Demo.Wasm/Pages/Index.razor
index 196dcf4..61b0a59 100644
--- a/Demo.Wasm/Pages/Index.razor
+++ b/Demo.Wasm/Pages/Index.razor
@@ -1,382 +1,378 @@
-@page "/"
+@page "/"
@page "/en"
+@page "/barcodereader"
+@inject NavigationManager NavigationManager
+
+
-BarcodeReader
-
-1D/2D barcode, QR code, Pdf417
-
- ShowScanBarcode = !ShowScanBarcode)">
- Scan
-
-
-
-
-Pdf417 Only
-
-
-
-Decode continuously
-
+
+
+
+
@L("在线扫码", "Live scanner")
+
@L("允许浏览器访问摄像头后即可开始扫码。", "Allow camera access in your browser to start scanning.")
+
+
+
+ @(ShowScanBarcode ? L("关闭扫码", "Close scanner") : L("开始扫码", "Start scanning"))
+
+
-
-Decodde all formats (+ PDF_417 / DATA_MATRIX...)
-
+
+
+
+ @L("仅解码 PDF417", "PDF417 only")
+
+
+
+ @L("连续解码", "Decode continuously")
+
+
+
+ @L("尝试所有格式", "Try all formats")
+
+
+
+ @L("扫码成功时截图", "Capture frame on scan")
+
+
-@if (Pdf417 | DecodeAllFormats)
-{
- Result:
-
- @BarCode
-}
-else if (DecodeContinuously)
-{
- DecodeContinuously:
-
- @BarCode
-}
-else
-{
-
-}
+ @if (CaptureStillOnScan)
+ {
+
+ @L("恢复预览延迟(毫秒)", "Preview resume delay (ms)")
+
+
+ }
-@if (ShowScanBarcode)
-{
+ @if (ShowScanBarcode)
+ {
+
+ }
-
+ @if (!string.IsNullOrWhiteSpace(ErrorMessage))
+ {
+ @ErrorMessage
+ }
-}
-
- ShowCodes = !ShowCodes)">
- Code
-
-
-@if (ShowCodes)
-{
-
-
- @@if (ShowScanBarcode)
+
+
+ @L("扫码结果", "Scan result")
+
+
+ @if (!string.IsNullOrWhiteSpace(CapturedImageDataUrl))
{
+
+
+ @L("最近一次扫码截图", "Latest captured frame")
+
+ }
+
+
- <BarcodeReader ScanResult="((e) => { BarCode=e; ShowScanBarcode = !ShowScanBarcode; })"
- Close="(()=>ShowScanBarcode=!ShowScanBarcode)"
- OnError="OnError" />
- @@code{
- bool ShowScanBarcode { get; set; } = false;
-
- public string? BarCode { get; set; }
-
- private string message;
-
- private Task OnError(string message)
- {
- this.message = message;
- StateHasChanged();
- return Task.CompletedTask;
- }
+
+
+
+
@L("从图片解码", "Decode from an image")
+
@L("选择本地图片并识别其中的条码。", "Choose a local image and decode its barcode.")
+
+
+ @L("选择图片", "Choose image")
+
+
+
+
+
+
+
+
+
@L("自定义扫码界面", "Custom scanner UI")
+
@L("关闭内置界面后,可用 data-action 元素控制扫码器。", "Disable the built-in UI and control the scanner with data-action elements.")
+
+
+ @(ShowCustomScanner ? L("关闭示例", "Close example") : L("打开示例", "Open example"))
+
+
- }
- }
-
-
-}
-@message
-
-
-
- Decode from image
-
-
-
-
- ShowScanBarcodeCustom = !ShowScanBarcodeCustom)">
- Scan code [customize]
-
-
-
-@if (ShowScanBarcodeCustom)
-{
-
-
-
-
-
-
-
+ @if (ShowCustomScanner)
+ {
+
+
+
+
- SelectDevice:
-
-
+ @L("摄像头", "Camera")
+
+
+
+ @L("扫码", "Scan")
+ @L("重置", "Reset")
+ @L("重新加载", "Reload")
+ @L("关闭", "Close")
-
Scan
-
Reset
-
await barcodeReaderCustom.Reload())">Reload
-
Close
+
+ }
+
+
+
+
+
@L("使用示例", "Usage")
+
@L("截图通过流式 JS 互操作返回,适用于 Blazor WebAssembly 和 Blazor Server。", "Captured frames are returned through streaming JS interop and work with both Blazor WebAssembly and Blazor Server.")
+
ShowCode = !ShowCode)">
+ @(ShowCode ? L("隐藏代码", "Hide code") : L("显示代码", "Show code"))
+
-
-
-}
-
-
-
-
-
-
-
Events
-
-
-
-
-
-
-
- ScanResult
- Scan result callback method
- EventCallback<string>
-
-
- Close
- Close scan code callback method
- EventCallback
-
-
- ScanBtnTitle
- Scan button title
- Parameter
-
-
- ResetBtnTitle
- Reset button title
- Parameter
-
-
- CloseBtnTitle
- Close button title
- Parameter
-
-
- Pdf417
- decode only Pdf417 format
- Parameter
-
-
- Decodeonce
- Decode Once or Decode Continuously, default is Once
- Parameter
-
-
- DecodeAllFormats
- Decodde All Formats, performance is poor, you can set options.formats to customize specify the encoding formats. The default is false
- Parameter
-
-
- options
-
-
- ZXingOptions: Pdf417 | Decodeonce | TimeBetweenDecodingAttempts | DecodeAllFormats | formats,
-
more...
-
-
- Parameter
- Parameter
-
-
- SelectDeviceBtnTitle
- Select device button title
- Parameter
-
-
- OnError
- Error callback method
- Func<string, Task>
-
+ @if (ShowCode)
+ {
+ @CodeSample
+ }
+
+
+
+ @L("事件", "Events")
+ @L("组件向调用方报告扫码结果、截图、关闭操作和错误。", "The component reports scan results, captured frames, close actions, and errors to its caller.")
+
+
+
+
+ @L("事件", "Event")
+ @L("类型", "Type")
+ @L("说明", "Description")
+
+
+
+ @foreach (var item in Events)
+ {
- UseBuiltinDiv
- Use builtin interface,defallt True
- bool
+ @item.Name
+ @item.Type
+ @L(item.Zh, item.En)
-
-
+ }
+
+
+
+
+
+
+ @L("主要参数", "Key parameters")
+
+ @L("以下参数覆盖界面、解码模式、摄像头选择和最新的扫码截图能力。完整高级解码提示可在 ZXingOptions 中配置。",
+ "These parameters cover UI, decoding modes, camera selection, and the latest scan-capture feature. Configure advanced decoding hints through ZXingOptions.")
+
+
+
+
+
+ @L("参数", "Parameter")
+ @L("类型", "Type")
+ @L("默认值", "Default")
+ @L("说明", "Description")
+
+
+
+ @foreach (var item in Parameters)
+ {
- Parameter
- Description
- Type
+ @item.Name
+ @item.Type
+ @item.DefaultValue
+ @L(item.Zh, item.En)
-
-
+ }
+
+
+
+
+ @L("查看完整 ZXingOptions", "View the complete ZXingOptions")
+
+
+
+
+ @L("支持的条码格式", "Supported barcode formats")
+
-
-
-
-
-
-
-
BarcodeFormat
-
-
-
-
- 1D product
- 1D industrial
- 2D
-
-
-
-
- UPC-A
- Code 39
- QR Code
-
-
- UPC-E
- Code 93
- Data Matrix
-
-
- EAN-8
- Code 128
- Aztec
-
-
- EAN-13
- Codabar
- PDF 417
-
-
-
- ITF
- MaxiCode
-
-
-
- RSS-14
-
-
-
-
- RSS-Expanded *
-
-
-
-
-
-
-
@ver
-
@build
-
-@code{
- BarCodes barCodes;
-
- ///
- /// Display the scan code interface
- ///
- bool ShowScanBarcode { get; set; } = false;
-
- ///
- /// BarCode
- ///
- public string? BarCode { get; set; }
-
- public bool Pdf417 { get; set; }
- public bool DecodeContinuously { get; set; }
- public bool DecodeAllFormats { get; set; }
-
- private string message;
-
- private Task OnError(string message)
+
+
+
+
+@code {
+ private readonly record struct ApiItem(string Name, string Type, string DefaultValue, string Zh, string En);
+
+ private static readonly ApiItem[] Events =
+ [
+ new("ScanResult", "EventCallback
", "-", "返回解码后的文本。启用截图时,在 ScanCaptured 完成后触发。", "Returns decoded text. When capture is enabled, it fires after ScanCaptured completes."),
+ new("ScanCaptured", "EventCallback", "-", "返回解码文本和当前视频帧的 JPEG Data URL。", "Returns the decoded text and a JPEG data URL for the current video frame."),
+ new("Close", "EventCallback", "-", "用户关闭扫码界面时触发。", "Raised when the user closes the scanner UI."),
+ new("OnError", "Func", "-", "摄像头、解码器或 JS 互操作出错时返回错误消息。", "Reports camera, decoder, or JS interop errors.")
+ ];
+
+ private static readonly ApiItem[] Parameters =
+ [
+ new("CaptureStillOnScan", "bool", "false", "扫码成功时冻结预览并捕获 JPEG 画面。", "Freezes the preview and captures a JPEG frame after a successful scan."),
+ new("CaptureStillAutoResumeDelay", "int", "3000", "捕获后恢复实时预览的延迟,单位为毫秒;最小值为 0。", "Delay in milliseconds before live preview resumes after capture; values are clamped to zero or greater."),
+ new("Decodeonce", "bool", "true", "单次解码;设为 false 时连续返回结果。", "Decodes once; set to false to keep reporting results."),
+ new("DecodeAllFormats", "bool", "false", "尝试全部格式,可能降低性能;可通过 Options.formats 缩小范围。", "Tries every format and may reduce performance; narrow the list with Options.formats."),
+ new("Pdf417Only", "bool", "false", "仅启用 PDF417 解码。", "Enables PDF417-only decoding."),
+ new("AlsoInverted", "bool", "true", "同时识别黑底白码等反色条码,并复用同一摄像头流。", "Also recognizes inverted barcodes, such as white-on-black codes, using the same camera stream."),
+ new("DeviceID", "string?", "null", "指定首选摄像头设备 ID。", "Selects a preferred camera device ID."),
+ new("SaveDeviceID", "bool", "true", "保存最后使用且仍然有效的摄像头设备 ID。", "Remembers the last selected camera when that device is still available."),
+ new("UseBuiltinDiv", "bool", "true", "使用组件内置扫码界面;设为 false 可提供自定义 data-action 元素。", "Uses the built-in scanner UI; set to false to provide custom data-action elements."),
+ new("Style", "ZXingBlazorStyle", "Modal", "选择内置界面的显示样式。", "Selects the presentation style of the built-in UI."),
+ new("Options", "ZXingOptions?", "null", "提供格式、图像尺寸、质量和高级 ZXing 解码提示。", "Provides formats, image dimensions, quality, and advanced ZXing decoding hints."),
+ new("ScanBtnTitle", "string", "\"扫码\"", "扫码按钮文本。", "Text shown on the scan button."),
+ new("ResetBtnTitle", "string", "\"复位\"", "重置按钮文本。", "Text shown on the reset button."),
+ new("CloseBtnTitle", "string", "\"关闭\"", "关闭按钮文本。", "Text shown on the close button."),
+ new("SelectDeviceBtnTitle", "string", "\"选择设备\"", "摄像头选择按钮文本。", "Text shown on the camera selection button.")
+ ];
+
+ private const string CodeSample = """
+
+
+@code {
+ private void OnScanResult(string text) { }
+ private void OnScanCaptured(ScanCapturedEventArgs args)
{
- this.message = message;
- StateHasChanged();
- return Task.CompletedTask;
+ // args.Text and args.ImageDataUrl
+ }
+}
+""";
+
+ private BarCodes barCodes = default!;
+ private BarcodeReader barcodeReaderCustom = default!;
+ private readonly ZXingOptions options = new() { TRY_HARDER = true };
+ private bool IsEnglish;
+ private bool ShowScanBarcode;
+ private bool ShowCustomScanner;
+ private bool ShowCode;
+ private bool Pdf417Only;
+ private bool DecodeContinuously;
+ private bool DecodeAllFormats;
+ private bool CaptureStillOnScan;
+ private int CaptureStillAutoResumeDelay = 3000;
+ private string BarCode = string.Empty;
+ private string? CapturedImageDataUrl;
+ private string? ErrorMessage;
+
+ private string VersionText =>
+ typeof(BarcodeReader).Assembly.GetName().Version?.ToString(3) ?? string.Empty;
+
+ private string L(string zh, string en) => IsEnglish ? en : zh;
+
+ protected override void OnInitialized()
+ {
+ IsEnglish = string.Equals(
+ NavigationManager.ToBaseRelativePath(NavigationManager.Uri).Trim('/'),
+ "en",
+ StringComparison.OrdinalIgnoreCase);
}
- bool ShowCodes;
+ private void ToggleLanguage() => IsEnglish = !IsEnglish;
- private void ScanResult(string e)
+ private void ToggleScanner()
{
- if (!DecodeContinuously)
- {
- BarCode = e;
- ShowScanBarcode = !ShowScanBarcode;
- }
- else
+ ShowScanBarcode = !ShowScanBarcode;
+ ErrorMessage = null;
+ if (ShowScanBarcode)
{
- if (BarCode.Length > 200) BarCode = "";
- BarCode += e + Environment.NewLine;
+ BarCode = string.Empty;
+ CapturedImageDataUrl = null;
}
}
- #region Custom
-
- ///
- /// Display the Custom scan code interface
- ///
- bool ShowScanBarcodeCustom { get; set; } = false;
-
- ///
- /// BarCodeCustom
- ///
- public string? BarCodeCustom { get; set; }
-
- BarcodeReader barcodeReaderCustom;
-
- #endregion
+ private void CloseScanner() => ShowScanBarcode = false;
+ private void OnScanResult(string text)
+ {
+ if (DecodeContinuously)
+ {
+ if (BarCode.Length > 500)
+ {
+ BarCode = string.Empty;
+ }
- string? ver { get; set; }
- string? build { get; set; }
-
+ BarCode += text + Environment.NewLine;
+ return;
+ }
- Version? version { get; set; } = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
+ BarCode = text;
+ ShowScanBarcode = false;
+ }
- protected override async Task OnInitializedAsync()
+ private void OnScanCaptured(ScanCapturedEventArgs args)
{
- await base.OnInitializedAsync();
-
- ver = $"Ver {version?.Major}.{version?.Minor}.{version?.Build}";
+ BarCode = args.Text;
+ CapturedImageDataUrl = args.ImageDataUrl;
+ }
+ private Task OnError(string message)
+ {
+ ErrorMessage = message;
+ return Task.CompletedTask;
}
- private ZXingOptions options = new ZXingOptions() { TRY_HARDER = true };
+ private void ToggleCustomScanner() => ShowCustomScanner = !ShowCustomScanner;
- private Task OnResult(string message)
+ private void OnCustomScanResult(string text)
{
- this.BarCode = message;
- StateHasChanged();
- return Task.CompletedTask;
+ BarCode = text;
+ ShowCustomScanner = false;
}
- private async Task DecodeFromImage()
+ private Task OnImageResult(string message)
{
- this.BarCode = "";
- this.message = "";
- await barCodes!.DecodeFromImage();
+ BarCode = message;
+ return Task.CompletedTask;
}
+
+ private Task DecodeFromImage() => barCodes.DecodeFromImage();
}
diff --git a/Demo.Wasm/Pages/Index.razor.css b/Demo.Wasm/Pages/Index.razor.css
new file mode 100644
index 0000000..f80ac04
--- /dev/null
+++ b/Demo.Wasm/Pages/Index.razor.css
@@ -0,0 +1,192 @@
+.demo-header,
+.section-heading {
+ align-items: flex-start;
+ display: flex;
+ gap: 1.5rem;
+ justify-content: space-between;
+}
+
+.demo-header {
+ background: linear-gradient(135deg, #f4f8ff, #eefbf7);
+ border: 1px solid #dce8f5;
+ border-radius: 1rem;
+ margin-bottom: 1.5rem;
+ padding: clamp(1.25rem, 4vw, 2.5rem);
+}
+
+.demo-header h1 {
+ font-size: clamp(2rem, 6vw, 3.5rem);
+ letter-spacing: -0.04em;
+ margin: 0.15rem 0 0.5rem;
+}
+
+.demo-header p,
+.section-heading p,
+.demo-section > p {
+ color: #5a6572;
+ margin-bottom: 0;
+}
+
+.eyebrow {
+ color: #0b6bcb;
+ font-size: 0.78rem;
+ font-weight: 700;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+}
+
+.language-button {
+ flex: 0 0 auto;
+}
+
+.demo-section {
+ border: 1px solid #e1e7ed;
+ border-radius: 0.85rem;
+ margin-bottom: 1.25rem;
+ padding: clamp(1rem, 3vw, 1.75rem);
+}
+
+.demo-section h2 {
+ font-size: 1.35rem;
+ margin-bottom: 0.35rem;
+}
+
+.demo-section h3 {
+ font-size: 1rem;
+}
+
+.section-heading {
+ margin-bottom: 1.25rem;
+}
+
+.option-grid {
+ display: grid;
+ gap: 0.75rem;
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
+ margin: 1rem 0;
+}
+
+.form-check {
+ background: #f7f9fb;
+ border: 1px solid #e1e7ed;
+ border-radius: 0.6rem;
+ cursor: pointer;
+ margin: 0;
+ padding: 0.8rem 0.9rem 0.8rem 2.25rem;
+}
+
+.delay-setting {
+ margin-bottom: 1rem;
+ max-width: 280px;
+}
+
+.delay-setting label {
+ display: block;
+ font-weight: 600;
+ margin-bottom: 0.4rem;
+}
+
+.result-grid {
+ display: grid;
+ gap: 1rem;
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+ margin-top: 1rem;
+}
+
+.result-field {
+ font-family: SFMono-Regular, Consolas, "Liberation Mono", monospace;
+}
+
+.capture-preview {
+ margin: 0;
+}
+
+.capture-preview img {
+ border: 1px solid #d5dde5;
+ border-radius: 0.6rem;
+ display: block;
+ max-height: 320px;
+ object-fit: contain;
+ width: 100%;
+}
+
+.capture-preview figcaption {
+ color: #5a6572;
+ font-size: 0.85rem;
+ margin-top: 0.45rem;
+}
+
+.custom-scanner {
+ max-width: 640px;
+}
+
+.custom-scanner video {
+ background: #101820;
+ border-radius: 0.7rem;
+ display: block;
+ max-height: 480px;
+ width: 100%;
+}
+
+.custom-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+ margin-top: 0.75rem;
+}
+
+.code-block {
+ background: #101820;
+ border-radius: 0.65rem;
+ color: #eaf2f8;
+ margin: 0;
+ overflow-x: auto;
+ padding: 1rem;
+}
+
+.api-table {
+ min-width: 720px;
+}
+
+.api-table code {
+ color: #174f88;
+ white-space: nowrap;
+}
+
+.format-groups {
+ display: grid;
+ gap: 1rem;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ margin-top: 1rem;
+}
+
+.format-groups > div {
+ background: #f7f9fb;
+ border-radius: 0.6rem;
+ padding: 1rem;
+}
+
+.format-groups p {
+ color: #5a6572;
+ margin: 0;
+}
+
+.demo-footer {
+ color: #71808f;
+ font-size: 0.85rem;
+ padding: 0.5rem 0 1.5rem;
+ text-align: center;
+}
+
+@media (max-width: 640px) {
+ .demo-header,
+ .section-heading {
+ align-items: stretch;
+ flex-direction: column;
+ }
+
+ .language-button,
+ .section-heading .btn {
+ align-self: flex-start;
+ }
+}
diff --git a/Demo.Wasm/Pages/Viewer.razor b/Demo.Wasm/Pages/Viewer.razor
deleted file mode 100644
index 8e5ee9e..0000000
--- a/Demo.Wasm/Pages/Viewer.razor
+++ /dev/null
@@ -1,25 +0,0 @@
-@page "/viewer"
- @using ZXingBlazor.Components
-
-
-
- @code{
- List Images;
- ViewerOptions ViewerOptions = new ViewerOptions()
- {
- toolbarlite = true,
- };
-
- protected override void OnInitialized()
- {
-
- Images = new List();
- if (!Images.Any())
- {
- for (int i = 1; i <= 9; i++)
- {
- Images.Add($"https://fengyuanchen.github.io/viewerjs/images/thumbnails/tibet-{i}.jpg");
- }
- }
- }
- }
diff --git a/Demo.Wasm/Shared/NavMenu.razor b/Demo.Wasm/Shared/NavMenu.razor
index c07da6e..bbab1cc 100644
--- a/Demo.Wasm/Shared/NavMenu.razor
+++ b/Demo.Wasm/Shared/NavMenu.razor
@@ -1,6 +1,6 @@
-
Demo.Wasm
+
ZXingBlazor
@@ -11,34 +11,9 @@
- Barcode
+ BarcodeReader
-
-
- 条码扫描 Barcode
-
-
-
-
- 手写签名 Handwritten
-
-
-
-
- 图片浏览器 Viewer
-
-
-
-
- ssr demo
-
-
-
-
- wasm demo
-
-