294 lines
8.4 KiB
C#
294 lines
8.4 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.JSInterop;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using EgwCoreLib.Utils;
|
|
using ZXingBlazor.Components;
|
|
|
|
namespace EgwCoreLib.Razor
|
|
{
|
|
public partial class BarcodeReader : IAsyncDisposable
|
|
{
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Close scan code callback method
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback Close { get; set; }
|
|
|
|
/// <summary>
|
|
/// Close button title
|
|
/// </summary>
|
|
[Parameter]
|
|
public string CloseBtnTitle { get; set; } = "Close";
|
|
|
|
/// <summary>
|
|
/// Decode All Formats, performance is poor, you can set options.formats to customize
|
|
/// specify the encoding formats. The default is false
|
|
/// </summary>
|
|
[Parameter]
|
|
public bool DecodeAllFormats { get; set; }
|
|
|
|
/// <summary>
|
|
/// Decode Once or Decode Continuously, default is Once
|
|
/// </summary>
|
|
[Parameter]
|
|
public bool Decodeonce { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Device ID
|
|
/// </summary>
|
|
[Parameter]
|
|
public string? DeviceID { get; set; }
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
public ElementReference Element { get; set; }
|
|
|
|
/// <summary>
|
|
/// Error callback method
|
|
/// </summary>
|
|
[Parameter]
|
|
public Func<string, Task>? OnError { get; set; }
|
|
|
|
/// <summary>
|
|
/// ZXingOptions
|
|
/// </summary>
|
|
[Parameter]
|
|
public ZXingOptions? Options { get; set; }
|
|
|
|
/// <summary>
|
|
/// Decode only Pdf417 format
|
|
/// </summary>
|
|
[Parameter]
|
|
public bool Pdf417Only { get; set; }
|
|
|
|
/// <summary>
|
|
/// Reset button title
|
|
/// </summary>
|
|
[Parameter]
|
|
public string ResetBtnTitle { get; set; } = "Reset";
|
|
|
|
/// <summary>
|
|
/// Save the last used device ID to be called automatically next time
|
|
/// </summary>
|
|
[Parameter]
|
|
public bool SaveDeviceID { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Scan button title
|
|
/// </summary>
|
|
[Parameter]
|
|
public string ScanBtnTitle { get; set; } = "Scan";
|
|
|
|
/// <summary>
|
|
/// Scan result callback method
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback<string> ScanResult { get; set; }
|
|
|
|
/// <summary>
|
|
/// Select device button title
|
|
/// </summary>
|
|
[Parameter]
|
|
public string SelectDeviceBtnTitle { get; set; } = "Select Device";
|
|
|
|
/// <summary>
|
|
/// Use builtin Div
|
|
/// </summary>
|
|
[Parameter] public bool UseBuiltinDiv { get; set; } = true;
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
[JSInvokable]
|
|
public async Task CloseScan() => await Close.InvokeAsync();
|
|
|
|
async ValueTask IAsyncDisposable.DisposeAsync()
|
|
{
|
|
await module!.InvokeVoidAsync("destroy", Element.Id);
|
|
Instance?.Dispose();
|
|
if (module is not null)
|
|
{
|
|
await module.DisposeAsync();
|
|
}
|
|
}
|
|
|
|
[JSInvokable]
|
|
public async Task GetError(string err)
|
|
{
|
|
if (OnError != null) await OnError.Invoke(err);
|
|
}
|
|
|
|
[JSInvokable]
|
|
public async Task GetResult(string val) => await ScanResult.InvokeAsync(val);
|
|
|
|
public async Task Reload()
|
|
{
|
|
await module!.InvokeVoidAsync("reload", Element.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 选择摄像头回调方法
|
|
/// </summary>
|
|
/// <param name="base64encodedstring"></param>
|
|
/// <returns></returns>
|
|
[JSInvokable]
|
|
public async Task SelectDeviceID(string deviceID, string deviceName)
|
|
{
|
|
try
|
|
{
|
|
if (SaveDeviceID)
|
|
{
|
|
await Storage.SetValue("CamsDeviceID", deviceID);
|
|
await Storage.SetValue("CamsDeviceName", deviceName);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
public async Task Start()
|
|
{
|
|
await module!.InvokeVoidAsync("start", Element.Id);
|
|
}
|
|
|
|
public async Task Stop()
|
|
{
|
|
await module!.InvokeVoidAsync("stop", Element.Id);
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Methods
|
|
|
|
// To prevent making JavaScript interop calls during prerendering
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
try
|
|
{
|
|
if (!firstRender) return;
|
|
Storage = new StorageService(JS);
|
|
module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/EgwCoreLib.Razor/BarcodeReader.razor.js");
|
|
#if false
|
|
module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/EgwCoreLib.Razor/BarcodeReader.razor.js" + "?v=" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
|
|
#endif
|
|
Instance = DotNetObjectReference.Create(this);
|
|
if (Options == null)
|
|
{
|
|
Options = new ZXingOptions()
|
|
{
|
|
Pdf417 = Pdf417Only,
|
|
Decodeonce = Decodeonce,
|
|
DecodeAllFormats = DecodeAllFormats,
|
|
//TRY_HARDER = true
|
|
};
|
|
}
|
|
try
|
|
{
|
|
if (SaveDeviceID)
|
|
{
|
|
DeviceID = await Storage.GetValue("CamsDeviceID", DeviceID);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
await module.InvokeVoidAsync("init", Instance, Element, Element.Id, Options, DeviceID);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
if (OnError != null) await OnError.Invoke(e.Message);
|
|
}
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private IJSObjectReference? module;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private DotNetObjectReference<BarcodeReader>? Instance { get; set; }
|
|
|
|
[Inject]
|
|
[NotNull]
|
|
private IJSRuntime? JS { get; set; }
|
|
|
|
[NotNull]
|
|
private StorageService? Storage { get; set; }
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Classes
|
|
|
|
private class StorageService
|
|
{
|
|
#region Public Constructors
|
|
|
|
public StorageService(IJSRuntime jsRuntime)
|
|
{
|
|
JSRuntime = jsRuntime;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
public static T? GetValueI<T>(string value)
|
|
{
|
|
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
|
|
if (converter != null)
|
|
{
|
|
return (T?)converter.ConvertFrom(value);
|
|
}
|
|
return default;
|
|
//return (T)Convert.ChangeType(value, typeof(T));
|
|
}
|
|
|
|
public async Task<TValue?> GetValue<TValue>(string key, TValue? def)
|
|
{
|
|
try
|
|
{
|
|
var cValue = await JSRuntime.InvokeAsync<TValue>("eval", $"localStorage.getItem('{key}');");
|
|
return cValue ?? def;
|
|
}
|
|
catch
|
|
{
|
|
var cValue = await JSRuntime.InvokeAsync<string>("eval", $"localStorage.getItem('{key}');");
|
|
if (cValue == null)
|
|
return def;
|
|
|
|
var newValue = GetValueI<TValue>(cValue);
|
|
return newValue ?? def;
|
|
}
|
|
}
|
|
|
|
public async Task RemoveValue(string key)
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("eval", $"localStorage.removeItem('{key}')");
|
|
}
|
|
|
|
public async Task SetValue<TValue>(string key, TValue value)
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("eval", $"localStorage.setItem('{key}', '{value}')");
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Fields
|
|
|
|
private readonly IJSRuntime JSRuntime;
|
|
|
|
#endregion Private Fields
|
|
}
|
|
|
|
#endregion Private Classes
|
|
}
|
|
} |