feat(TagHelper): add BootstrapBlazor.TagHelper package (#3278)

* doc: 增加压缩

* refactor: 代码格式化

* refactor: 更改变量名

* refactor: 优化代码

* chore: 移除版本信息

* refactor: 增加压缩配置

* refactor: 使用原生标签

* refactor: 移除缓存配置

* chore: 移除工具链

* chore: 移除代码内置依赖服务

* doc: 移除 xml 注释

* refactor: 更新缓存策略

* doc: 格式化文档

* Revert "refactor: 使用原生标签"

This reverts commit 00da9357f75672ccfe8b1322391964435ce483e8.

* doc: 增加字典

* doc: 移除 jQuery 显示引用

* Revert "doc: 移除 jQuery 显示引用"

This reverts commit f81512f340bdd64874a27b151a5f55e600514f2f.

* feat: 增加文件哈希值逻辑

* chore: 更新路由

* doc: 更新注释

* feat: 增加 HashFile 方法

* doc: 格式化文档

* revert: 移除方法

* refactor: 更改属性标签顺序

* refactor: 使用原生标签

* chore: 更新自动化脚本

* revert: 撤销 WebRootPath 参数

* feat: 增加 TagHelper 工程

* doc: 格式化文档

* test: 更新单元测试
This commit is contained in:
Argo Zhang 2024-04-13 21:09:29 +08:00 committed by GitHub
parent 576e4d2f1c
commit 998a878854
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
105 changed files with 316 additions and 343 deletions

View File

@ -132,6 +132,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BootstrapBlazor.Maui", "src
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "maui", "maui", "{81615751-490B-4B50-8029-C79846F592BB}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "maui", "maui", "{81615751-490B-4B50-8029-C79846F592BB}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.TagHelper", "src\Extensions\Components\BootstrapBlazor.TagHelper\BootstrapBlazor.TagHelper.csproj", "{65CEB170-D561-4878-80E4-625538590D29}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -292,6 +294,10 @@ Global
{B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.Build.0 = Release|Any CPU {B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.Build.0 = Release|Any CPU
{B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.Deploy.0 = Release|Any CPU {B94D32F4-2E7C-400B-BC34-D6BA31A234CB}.Release|Any CPU.Deploy.0 = Release|Any CPU
{65CEB170-D561-4878-80E4-625538590D29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65CEB170-D561-4878-80E4-625538590D29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65CEB170-D561-4878-80E4-625538590D29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65CEB170-D561-4878-80E4-625538590D29}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -343,6 +349,7 @@ Global
{AB19F805-A27F-455F-8E36-8F1ADE295868} = {7C1D79F1-87BC-42C1-BD5A-CDE4044AC1BD} {AB19F805-A27F-455F-8E36-8F1ADE295868} = {7C1D79F1-87BC-42C1-BD5A-CDE4044AC1BD}
{B94D32F4-2E7C-400B-BC34-D6BA31A234CB} = {81615751-490B-4B50-8029-C79846F592BB} {B94D32F4-2E7C-400B-BC34-D6BA31A234CB} = {81615751-490B-4B50-8029-C79846F592BB}
{81615751-490B-4B50-8029-C79846F592BB} = {A2182155-43ED-44C1-BF6F-1B70EBD2DFFE} {81615751-490B-4B50-8029-C79846F592BB} = {A2182155-43ED-44C1-BF6F-1B70EBD2DFFE}
{65CEB170-D561-4878-80E4-625538590D29} = {CD062AB6-244D-402A-8F33-C37DAC5856CC}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0DCB0756-34FA-4FD0-AE1D-D3F08B5B3A6B} SolutionGuid = {0DCB0756-34FA-4FD0-AE1D-D3F08B5B3A6B}

View File

@ -8,7 +8,6 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)src\keys\Longbow.Utility.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)src\keys\Longbow.Utility.snk</AssemblyOriginatorKeyFile>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -80,3 +80,4 @@ Cascader
Cascaders Cascaders
maui maui
gantt gantt
jquery

View File

@ -1,4 +1,4 @@
@inject IHostEnvironment Env @inject IWebHostEnvironment Env
@inject IStringLocalizer<App> Localizer @inject IStringLocalizer<App> Localizer
<!DOCTYPE html> <!DOCTYPE html>
@ -12,19 +12,19 @@
<meta name="keywords" content="bootstrap,blazor,wasm,webassembly,UI,netcore,web,assembly"> <meta name="keywords" content="bootstrap,blazor,wasm,webassembly,UI,netcore,web,assembly">
<meta name="description" content="基于 Bootstrap 风格的 Blazor UI 组件库,用于研发企业级中后台产品。"> <meta name="description" content="基于 Bootstrap 风格的 Blazor UI 组件库,用于研发企业级中后台产品。">
<meta name="author" content="argo (argo@live.ca)"> <meta name="author" content="argo (argo@live.ca)">
<base href="/" />
<link rel="icon" href="favicon.ico" type="image/x-icon"> <link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="favicon.png"> <link rel="apple-touch-icon" href="favicon.png">
<base href="/" /> <link rel="stylesheet" href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" />
<Link Href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" /> <link rel="stylesheet" href="_content/BootstrapBlazor.MaterialDesign/css/md.min.css" />
<Link Href="_content/BootstrapBlazor.MaterialDesign/css/md.min.css" /> <link rel="stylesheet" href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" />
<Link Href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" /> <link rel="stylesheet" href="_content/BootstrapBlazor/css/motronic.min.css" />
<Link Href="_content/BootstrapBlazor/css/motronic.min.css" /> <link rel="stylesheet" href="BootstrapBlazor.Server.styles.css" />
<Link Href="BootstrapBlazor.Server.styles.css" /> <link rel="stylesheet" href="css/site.css" />
<Link Href="css/site.css" /> <script src="lib/theme.js" type="module"></script>
<title>@Localizer["Title"]</title>
<HeadOutlet @rendermode="new InteractiveServerRenderMode(false)" /> <HeadOutlet @rendermode="new InteractiveServerRenderMode(false)" />
<Script Src="lib/theme.js" type="module"></Script> <title>@Localizer["Title"]</title>
</head> </head>
<body> <body>
@ -36,14 +36,14 @@
<BlazorReconnector @rendermode="new InteractiveServerRenderMode(false)" /> <BlazorReconnector @rendermode="new InteractiveServerRenderMode(false)" />
<Script Src="_content/BootstrapBlazor.SummerNote/js/jquery-3.5.1.min.js"></Script> <script src="_content/BootstrapBlazor.SummerNote/js/jquery-3.5.1.min.js"></script>
@if (Env.IsDevelopment()) @if (Env.IsDevelopment())
{ {
<Script Src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.js"></Script> <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.js"></script>
} }
@if (Env.IsProduction()) @if (Env.IsProduction())
{ {
<Script Src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></Script> <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
} }
<script src="_framework/blazor.web.js"></script> <script src="_framework/blazor.web.js"></script>
@if (Env.IsProduction()) @if (Env.IsProduction())

View File

@ -1,5 +1,5 @@
import { getPreferredTheme, setTheme } from "../../_content/BootstrapBlazor/modules/theme.js?v=$version" import { getPreferredTheme, setTheme } from "../../_content/BootstrapBlazor/modules/theme.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export function init() { export function init() {
const scrollTop = () => (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop const scrollTop = () => (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop

View File

@ -1,5 +1,5 @@
import { copy, getDescribedElement, addLink, addScript, getHeight } from "../../_content/BootstrapBlazor/modules/utility.js?v=$version" import { copy, getDescribedElement, addLink, addScript, getHeight } from "../../_content/BootstrapBlazor/modules/utility.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export async function init(id, title) { export async function init(id, title) {
const el = document.getElementById(id); const el = document.getElementById(id);

View File

@ -1,6 +1,6 @@
import { insertAfter } from "../../_content/BootstrapBlazor/modules/utility.js?v=$version" import { insertAfter } from "../../_content/BootstrapBlazor/modules/utility.js"
import Data from "../../_content/BootstrapBlazor/modules/data.js?v=$version" import Data from "../../_content/BootstrapBlazor/modules/data.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../_content/BootstrapBlazor/modules/data.js?v=$version" import Data from "../../_content/BootstrapBlazor/modules/data.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export function init(id, version) { export function init(id, version) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -47,13 +47,6 @@ public partial class ComponentLayout : IAsyncDisposable
/// </summary> /// </summary>
private JSModule? Module { get; set; } private JSModule? Module { get; set; }
/// <summary>
/// 获得 IVersionService 服务实例
/// </summary>
[Inject]
[NotNull]
private IVersionService? JSVersionService { get; set; }
[Inject] [Inject]
[NotNull] [NotNull]
private IOptions<IconThemeOptions>? IconThemeOptions { get; set; } private IOptions<IconThemeOptions>? IconThemeOptions { get; set; }
@ -109,7 +102,7 @@ public partial class ComponentLayout : IAsyncDisposable
{ {
if (firstRender) if (firstRender)
{ {
Module = await JSRuntime.LoadModule("./Components/Layout/ComponentLayout.razor.js", JSVersionService.GetVersion()); Module = await JSRuntime.LoadModule("./Components/Layout/ComponentLayout.razor.js");
} }
if (Module != null) if (Module != null)
{ {

View File

@ -23,13 +23,6 @@ public partial class DockLayout : IAsyncDisposable
[NotNull] [NotNull]
private IJSRuntime? JSRuntime { get; set; } private IJSRuntime? JSRuntime { get; set; }
/// <summary>
/// 获得 IVersionService 服务实例
/// </summary>
[Inject]
[NotNull]
private IVersionService? JSVersionService { get; set; }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
@ -39,7 +32,7 @@ public partial class DockLayout : IAsyncDisposable
{ {
if (firstRender) if (firstRender)
{ {
Module = await JSRuntime.LoadModule("./Components/Layout/DockLayout.razor.js", JSVersionService.GetVersion()); Module = await JSRuntime.LoadModule("./Components/Layout/DockLayout.razor.js");
await Module.InvokeVoidAsync("init"); await Module.InvokeVoidAsync("init");
} }
} }

View File

@ -1,6 +1,6 @@
import Data from "../../_content/BootstrapBlazor/modules/data.js?v=$version" import Data from "../../_content/BootstrapBlazor/modules/data.js"
import Drag from "../../_content/BootstrapBlazor/modules/drag.js?v=$version" import Drag from "../../_content/BootstrapBlazor/modules/drag.js"
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export function init(id) { export function init(id) {
const navmenu = { const navmenu = {

View File

@ -24,10 +24,6 @@ public partial class Chats
[NotNull] [NotNull]
private IBrowserFingerService? BrowserFingerService { get; set; } private IBrowserFingerService? BrowserFingerService { get; set; }
[Inject]
[NotNull]
private IVersionService? VersionService { get; set; }
private string? Context { get; set; } private string? Context { get; set; }
private List<AzureOpenAIChatMessage> Messages { get; } = []; private List<AzureOpenAIChatMessage> Messages { get; } = [];
@ -129,7 +125,7 @@ public partial class Chats
private async Task<string> GetFingerCodeAsync() private async Task<string> GetFingerCodeAsync()
{ {
var code = await BrowserFingerService.GetFingerCodeAsync(); var code = await BrowserFingerService.GetFingerCodeAsync();
code ??= $"BootstrapBlazor{VersionService.GetVersion()}"; code ??= "BootstrapBlazor";
return code; return code;
} }

View File

@ -1,4 +1,4 @@
import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../_content/BootstrapBlazor/modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,4 +1,4 @@
import Data from '../../_content/BootstrapBlazor/modules/data.js?v=$version' import Data from '../../_content/BootstrapBlazor/modules/data.js'
export function init(id, text1, text2, text3) { export function init(id, text1, text2, text3) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import Data from '../../../_content/BootstrapBlazor/modules/data.js?v=$version' import Data from '../../../_content/BootstrapBlazor/modules/data.js'
import EventHandler from "../../../_content/BootstrapBlazor/modules/event-handler.js?v=$version" import EventHandler from "../../../_content/BootstrapBlazor/modules/event-handler.js"
import { isMobile } from "../../../_content/BootstrapBlazor/modules/utility.js?v=$version" import { isMobile } from "../../../_content/BootstrapBlazor/modules/utility.js"
/** /**
* 缓存绘图步骤 * 缓存绘图步骤

View File

@ -1,6 +1,6 @@
<Project> <Project>
<Import Project="..\Version.targets" /> <Import Project="..\Version.targets" Condition="'$(TargetFramework)' == 'net1.0'" />
<Target Name="PostPublish" AfterTargets="Publish" Condition="'$(Configuration)' == 'Release'"> <Target Name="PostPublish" AfterTargets="Publish" Condition="'$(Configuration)' == 'Release'">
<Exec Command="git reset --hard"></Exec> <Exec Command="git reset --hard"></Exec>

View File

@ -44,8 +44,9 @@ internal static class ServicesExtensions
// 增加多语言支持配置信息 // 增加多语言支持配置信息
services.AddRequestLocalization<IOptionsMonitor<BootstrapBlazorOptions>>((localizerOption, blazorOption) => services.AddRequestLocalization<IOptionsMonitor<BootstrapBlazorOptions>>((localizerOption, blazorOption) =>
{ {
blazorOption.OnChange(op => Invoke(op)); blazorOption.OnChange(Invoke);
Invoke(blazorOption.CurrentValue); Invoke(blazorOption.CurrentValue);
return;
void Invoke(BootstrapBlazorOptions option) void Invoke(BootstrapBlazorOptions option)
{ {

View File

@ -3,15 +3,11 @@
// Website: https://www.blazor.zone or https://argozhang.github.io/ // Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
namespace BootstrapBlazor.Server.Extensions; namespace BootstrapBlazor.Server.Extensions;
/// <summary> internal static class StaticFileResponseContextExtensions
///
/// </summary>
internal static class CacheExtensions
{ {
public static void ProcessCache(this StaticFileResponseContext context, IConfiguration configuration) public static void ProcessCache(this StaticFileResponseContext context, IConfiguration configuration)
{ {
@ -26,8 +22,8 @@ internal static class CacheExtensions
var ret = false; var ret = false;
age = 0; age = 0;
var files = configuration.GetFiles(); var fileTypes = configuration.GetFileTypes();
if (files.Any(i => context.CanCache(i))) if (fileTypes.Any(context.CanCache))
{ {
ret = true; ret = true;
age = configuration.GetAge(); age = configuration.GetAge();
@ -35,30 +31,19 @@ internal static class CacheExtensions
return ret; return ret;
} }
private static bool CanCache(this StaticFileResponseContext context, string file) private static bool CanCache(this StaticFileResponseContext context, string fileType)
{ {
var ext = Path.GetExtension(context.File.PhysicalPath) ?? ""; var ext = Path.GetExtension(context.File.PhysicalPath) ?? "";
bool ret = file.Equals(ext, StringComparison.OrdinalIgnoreCase); return fileType.Equals(ext, StringComparison.OrdinalIgnoreCase);
if (ret && ext.Equals(".js", StringComparison.OrdinalIgnoreCase))
{
// process javascript file
ret = false;
if (context.Context.Request.QueryString.HasValue)
{
var paras = QueryHelpers.ParseQuery(context.Context.Request.QueryString.Value);
ret = paras.ContainsKey("v");
}
}
return ret;
} }
private static List<string>? _files; private static List<string>? _fileTypes;
private static List<string> GetFiles(this IConfiguration configuration) private static List<string> GetFileTypes(this IConfiguration configuration)
{ {
_files ??= GetFiles(); _fileTypes ??= GetFilesFromConfiguration();
return _files; return _fileTypes;
List<string> GetFiles() List<string> GetFilesFromConfiguration()
{ {
var cacheSection = configuration.GetSection("Cache-Control"); var cacheSection = configuration.GetSection("Cache-Control");
return cacheSection.GetSection("Files").Get<List<string>>() ?? []; return cacheSection.GetSection("Files").Get<List<string>>() ?? [];
@ -68,13 +53,13 @@ internal static class CacheExtensions
private static int? _age; private static int? _age;
private static int GetAge(this IConfiguration configuration) private static int GetAge(this IConfiguration configuration)
{ {
_age ??= GetAge(); _age ??= GetAgeFromConfiguration();
return _age.Value; return _age.Value;
int GetAge() int GetAgeFromConfiguration()
{ {
var cacheSection = configuration.GetSection("Cache-Control"); var cacheSection = configuration.GetSection("Cache-Control");
return cacheSection.GetValue<int>("Max-Age", 1000 * 60 * 10); return cacheSection.GetValue("Max-Age", 1000 * 60 * 10);
} }
} }
} }

View File

@ -21,7 +21,14 @@ builder.Services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));
builder.Services.AddLogging(logBuilder => logBuilder.AddFileLogger()); builder.Services.AddLogging(logBuilder => logBuilder.AddFileLogger());
builder.Services.AddCors(); builder.Services.AddCors();
builder.Services.AddResponseCompression();
#if DEBUG
#else
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
});
#endif
builder.Services.AddControllers(); builder.Services.AddControllers();
builder.Services.AddRazorComponents().AddInteractiveServerComponents(); builder.Services.AddRazorComponents().AddInteractiveServerComponents();
@ -48,14 +55,19 @@ if (!app.Environment.IsDevelopment())
{ {
app.UseExceptionHandler("/Error"); app.UseExceptionHandler("/Error");
app.UseResponseCompression(); app.UseResponseCompression();
app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => ctx.ProcessCache(app.Configuration) });
} }
app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => ctx.ProcessCache(app.Configuration) });
var provider = new FileExtensionContentTypeProvider(); var provider = new FileExtensionContentTypeProvider
provider.Mappings[".properties"] = "application/octet-stream"; {
provider.Mappings[".moc"] = "application/x-msdownload"; Mappings =
provider.Mappings[".moc3"] = "application/x-msdownload"; {
provider.Mappings[".mtn"] = "application/x-msdownload"; [".properties"] = "application/octet-stream",
[".moc"] = "application/x-msdownload",
[".moc3"] = "application/x-msdownload",
[".mtn"] = "application/x-msdownload"
}
};
app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider }); app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
app.UseStaticFiles(); app.UseStaticFiles();
@ -63,7 +75,7 @@ app.UseStaticFiles();
var cors = app.Configuration["AllowOrigins"]?.Split(',', StringSplitOptions.RemoveEmptyEntries); var cors = app.Configuration["AllowOrigins"]?.Split(',', StringSplitOptions.RemoveEmptyEntries);
if (cors?.Length > 0) if (cors?.Length > 0)
{ {
app.UseCors(builder => builder.WithOrigins() app.UseCors(options => options.WithOrigins()
.AllowAnyHeader() .AllowAnyHeader()
.AllowAnyMethod() .AllowAnyMethod()
.AllowCredentials()); .AllowCredentials());

View File

@ -226,7 +226,7 @@ code {
top: .65rem; top: .65rem;
right: 1.5rem; right: 1.5rem;
font-size: 65%; font-size: 65%;
transition: opacity .3s linear; transition: opacity .3s linear;
} }
.btn-code:not(:hover) { .btn-code:not(:hover) {

View File

@ -1,3 +1,3 @@
import { getPreferredTheme, setTheme } from "../../_content/BootstrapBlazor/modules/theme.js?v=$version" import { getPreferredTheme, setTheme } from "../../_content/BootstrapBlazor/modules/theme.js"
setTheme(getPreferredTheme()) setTheme(getPreferredTheme())

View File

@ -1,5 +1,5 @@
import { getDescribedElement, getOverflowParent } from "../../modules/utility.js?v=$version" import { getDescribedElement, getOverflowParent } from "../../modules/utility.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import { copy } from "../../modules/utility.js?v=$version" import { copy } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,9 +1,9 @@
import { debounce, getHeight } from "../../modules/utility.js?v=$version" import { debounce, getHeight } from "../../modules/utility.js"
import { handleKeyUp, select, selectAllByFocus, selectAllByEnter } from "../Input/BootstrapInput.razor.js?v=$version" import { handleKeyUp, select, selectAllByFocus, selectAllByEnter } from "../Input/BootstrapInput.razor.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import Input from "../../modules/input.js?v=$version" import Input from "../../modules/input.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id, invoke) { export function init(id, invoke) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -36,13 +36,6 @@ public abstract class BootstrapModuleComponentBase : IdComponentBase, IAsyncDisp
/// </summary> /// </summary>
protected DotNetObjectReference<BootstrapModuleComponentBase>? Interop { get; set; } protected DotNetObjectReference<BootstrapModuleComponentBase>? Interop { get; set; }
/// <summary>
/// 获得 IVersionService 服务实例
/// </summary>
[Inject]
[NotNull]
protected IVersionService? JSVersionService { get; set; }
/// <summary> /// <summary>
/// <inheritdoc/> /// <inheritdoc/>
/// </summary> /// </summary>
@ -61,7 +54,7 @@ public abstract class BootstrapModuleComponentBase : IdComponentBase, IAsyncDisp
{ {
if (firstRender && !string.IsNullOrEmpty(ModulePath)) if (firstRender && !string.IsNullOrEmpty(ModulePath))
{ {
Module ??= await JSRuntime.LoadModule(ModulePath, JSVersionService.GetVersion()); Module ??= await JSRuntime.LoadModule(ModulePath);
if (AutoInvokeInit) if (AutoInvokeInit)
{ {

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
const showTooltip = (id, title) => { const showTooltip = (id, title) => {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,7 +1,7 @@
import { getDescribedElement, getDescribedOwner, hackPopover, isDisabled } from "../../modules/utility.js?v=$version" import { getDescribedElement, getDescribedOwner, hackPopover, isDisabled } from "../../modules/utility.js"
import { showTooltip, removeTooltip } from "./Button.razor.js?v=$version" import { showTooltip, removeTooltip } from "./Button.razor.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const config = { const config = {
class: 'popover-confirm', class: 'popover-confirm',

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
const openDevice = camera => { const openDevice = camera => {
if(camera.video) { if(camera.video) {

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Drag from "../../modules/drag.js?v=$version" import Drag from "../../modules/drag.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback, option) { export function init(id, invoke, callback, option) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, options) { export function init(id, options) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Drag from "../../modules/drag.js?v=$version" import Drag from "../../modules/drag.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const setValue = (picker, point, value) => { const setValue = (picker, point, value) => {
const { el, val } = picker; const { el, val } = picker;

View File

@ -1,5 +1,5 @@
import { getHeight } from "../../modules/utility.js?v=$version" import { getHeight } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id) { export function init(id) {
const con = { const con = {

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import { createPopper, computePosition } from '../../modules/floating-ui.js?v=$version' import { createPopper, computePosition } from '../../modules/floating-ui.js'
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import { CountUp } from "../../lib/countUp/countUp.min.js?v=$version" import { CountUp } from "../../lib/countUp/countUp.min.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id, invoke, val, callback, option) { export function init(id, invoke, val, callback, option) {
option = option || {} option = option || {}

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import { copy } from "../../modules/utility.js?v=$version" import { copy } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Drag from "../../modules/drag.js?v=$version" import Drag from "../../modules/drag.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id, options) { export function init(id, options) {
options = { options = {

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const getScrollElement = el => { const getScrollElement = el => {
let ele = el let ele = el

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
//当页面高度超过设备可见高度时阻止掉touchmove事件。 //当页面高度超过设备可见高度时阻止掉touchmove事件。

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const handler = e => { const handler = e => {

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Viewer from "../../modules/viewer.js?v=$version" import Viewer from "../../modules/viewer.js"
export function init(id, prevList) { export function init(id, prevList) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const setListeners = (viewer, index) => { const setListeners = (viewer, index) => {
if (viewer.prevList && viewer.prevList.length > 0) { if (viewer.prevList && viewer.prevList.length > 0) {

View File

@ -1,4 +1,4 @@
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function clear(id) { export function clear(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const selectCell = (el, index) => { const selectCell = (el, index) => {
if (index === -1) { if (index === -1) {

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const layout = { const layout = {

View File

@ -1,5 +1,5 @@
import { getTargetElement, getTransitionDelayDurationFromElement } from "../../modules/utility.js?v=$version" import { getTargetElement, getTransitionDelayDurationFromElement } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, shownCallback, closeCallback) { export function init(id, invoke, shownCallback, closeCallback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import { drag } from "../../modules/utility.js?v=$version" import { drag } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,7 +1,7 @@
import { getUID } from "../../modules/utility.js?v=$version" import { getUID } from "../../modules/utility.js"
import { showTooltip, removeTooltip } from "../Button/Button.razor.js?v=$version" import { showTooltip, removeTooltip } from "../Button/Button.razor.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from '../../modules/data.js?v=$version' import Data from '../../modules/data.js'
import EventHandler from '../../modules/event-handler.js?v=$version' import EventHandler from '../../modules/event-handler.js'
export function init(id, invoke) { export function init(id, invoke) {
const el = document.getElementById(id); const el = document.getElementById(id);

View File

@ -1,7 +1,7 @@
import { isDisabled } from "../../modules/utility.js?v=$version" import { isDisabled } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, method) { export function init(id, invoke, method) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,7 +1,7 @@
import { getHeight, getInnerHeight } from "../../modules/utility.js?v=$version" import { getHeight, getInnerHeight } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id, invoke, method) { export function init(id, invoke, method) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import { getWidth } from "../../modules/utility.js?v=$version" import { getWidth } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import { getWidth } from "../../modules/utility.js?v=$version" import { getWidth } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,7 +1,7 @@
import { getHeight, getInnerHeight } from "../../modules/utility.js?v=$version" import { getHeight, getInnerHeight } from "../../modules/utility.js"
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import Drag from "../../modules/drag.js?v=$version" import Drag from "../../modules/drag.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
const getPosition = el => { const getPosition = el => {
return el.getBoundingClientRect(); return el.getBoundingClientRect();

View File

@ -1,9 +1,9 @@
export { getResponsive } from '../../modules/responsive.js?v=$version' export { getResponsive } from '../../modules/responsive.js'
import { copy, drag, getDescribedElement, getOuterHeight, getWidth, isVisible } from '../../modules/utility.js?v=$version' import { copy, drag, getDescribedElement, getOuterHeight, getWidth, isVisible } from '../../modules/utility.js'
import '../../modules/browser.js?v=$version' import '../../modules/browser.js'
import Data from '../../modules/data.js?v=$version' import Data from '../../modules/data.js'
import EventHandler from '../../modules/event-handler.js?v=$version' import EventHandler from '../../modules/event-handler.js'
import Popover from "../../modules/base-popover.js?v=$version" import Popover from "../../modules/base-popover.js"
const setBodyHeight = table => { const setBodyHeight = table => {
const el = table.el const el = table.el

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id) { export function init(id) {
const text = { const text = {

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke) { export function init(id, invoke) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,4 +1,4 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,4 +1,4 @@
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,5 +1,5 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -434,7 +434,7 @@ public abstract class ValidateBase<TValue> : DisplayBase<TValue>, IValidateCompo
private JSModule? ValidateModule { get; set; } private JSModule? ValidateModule { get; set; }
private Task<JSModule> LoadValidateModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/validate.js", JSVersionService.GetVersion()); private Task<JSModule> LoadValidateModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/validate.js");
/// <summary> /// <summary>
/// 增加客户端 Tooltip 方法 /// 增加客户端 Tooltip 方法

View File

@ -1,4 +1,4 @@
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -1,6 +1,6 @@
import Data from "../../modules/data.js?v=$version" import Data from "../../modules/data.js"
import EventHandler from "../../modules/event-handler.js?v=$version" import EventHandler from "../../modules/event-handler.js"
import { debounce } from "../../modules/utility.js?v=$version" import { debounce } from "../../modules/utility.js"
const cal = (el, imgWidth) => { const cal = (el, imgWidth) => {
const containerWidth = el.offsetWidth; const containerWidth = el.offsetWidth;

View File

@ -5,7 +5,7 @@
<Import Project="..\Logo.props" /> <Import Project="..\Logo.props" />
<Import Project="..\Bundle.props" /> <Import Project="..\Bundle.props" />
<Import Project="..\SourceLink.targets" /> <Import Project="..\SourceLink.targets" />
<Import Project="..\Version.targets" /> <Import Project="..\Version.targets" Condition="'$(TargetFramework)' == 'net1.0'" />
<PropertyGroup> <PropertyGroup>
<PackageTags>Bootstrap Blazor WebAssembly wasm UI Components</PackageTags> <PackageTags>Bootstrap Blazor WebAssembly wasm UI Components</PackageTags>

View File

@ -16,22 +16,18 @@ class DefaultGeoLocationService : IGeoLocationService
private long WatchId { get; set; } private long WatchId { get; set; }
private IVersionService JSVersionService { get; }
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="jsRuntime"></param> /// <param name="jsRuntime"></param>
/// <param name="versionService"></param> public DefaultGeoLocationService(IJSRuntime jsRuntime)
public DefaultGeoLocationService(IJSRuntime jsRuntime, IVersionService versionService)
{ {
JSRuntime = jsRuntime; JSRuntime = jsRuntime;
JSVersionService = versionService;
Interop = DotNetObjectReference.Create(this); Interop = DotNetObjectReference.Create(this);
} }
private Task<JSModule> LoadModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/geo.js", JSVersionService.GetVersion()); private Task<JSModule> LoadModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/geo.js");
/// <summary> /// <summary>
/// get the current position of the device /// get the current position of the device

View File

@ -19,23 +19,19 @@ public class NotificationService : IAsyncDisposable
private ICacheManager Cache { get; } private ICacheManager Cache { get; }
private IVersionService JSVersionService { get; }
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="runtime"></param> /// <param name="runtime"></param>
/// <param name="cache"></param> /// <param name="cache"></param>
/// <param name="versionService"></param> public NotificationService(IJSRuntime runtime, ICacheManager cache)
public NotificationService(IJSRuntime runtime, ICacheManager cache, IVersionService versionService)
{ {
JSRuntime = runtime; JSRuntime = runtime;
Cache = cache; Cache = cache;
JSVersionService = versionService;
Interop = DotNetObjectReference.Create(this); Interop = DotNetObjectReference.Create(this);
} }
private Task<JSModule> LoadModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/noti.js", JSVersionService.GetVersion()); private Task<JSModule> LoadModule() => JSRuntime.LoadModule("./_content/BootstrapBlazor/modules/noti.js");
/// <summary> /// <summary>
/// 检查浏览器通知权限状态 /// 检查浏览器通知权限状态

View File

@ -12,12 +12,10 @@ namespace BootstrapBlazor.Components;
/// </summary> /// </summary>
/// <param name="runtime"></param> /// <param name="runtime"></param>
/// <param name="navigation"></param> /// <param name="navigation"></param>
/// <param name="versionService"></param>
/// <param name="logger"></param> /// <param name="logger"></param>
public class WebClientService( public class WebClientService(
IJSRuntime runtime, IJSRuntime runtime,
NavigationManager navigation, NavigationManager navigation,
IVersionService versionService,
ILogger<WebClientService> logger) : IAsyncDisposable ILogger<WebClientService> logger) : IAsyncDisposable
{ {
/// <summary> /// <summary>
@ -42,7 +40,7 @@ public class WebClientService(
{ {
RequestUrl = navigation.Uri RequestUrl = navigation.Uri
}; };
_jsModule ??= await runtime.LoadModule("./_content/BootstrapBlazor/modules/client.js", versionService.GetVersion()); _jsModule ??= await runtime.LoadModule("./_content/BootstrapBlazor/modules/client.js");
_interop ??= DotNetObjectReference.Create(this); _interop ??= DotNetObjectReference.Create(this);
await _jsModule.InvokeVoidAsync("ping", "ip.axd", _interop, nameof(SetData)); await _jsModule.InvokeVoidAsync("ping", "ip.axd", _interop, nameof(SetData));

View File

@ -596,7 +596,7 @@ public static class Utility
/// 通过指定类型生成组件类型 /// 通过指定类型生成组件类型
/// </summary> /// </summary>
/// <param name="fieldType"></param> /// <param name="fieldType"></param>
/// <param name="hasRows">是否为 Textarea 组件</param> /// <param name="hasRows">是否为 TextArea 组件</param>
/// <param name="lookup"></param> /// <param name="lookup"></param>
/// <returns></returns> /// <returns></returns>
private static Type GenerateComponentType(Type fieldType, bool hasRows, IEnumerable<SelectedItem>? lookup) private static Type GenerateComponentType(Type fieldType, bool hasRows, IEnumerable<SelectedItem>? lookup)

View File

@ -1,5 +1,5 @@
import Data from "./data.js?v=$version" import Data from "./data.js"
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export function init(id, invoke, interval, callback) { export function init(id, invoke, interval, callback) {
const m = { invoke, interval, callback, mousePosition: {}, count: 1000 } const m = { invoke, interval, callback, mousePosition: {}, count: 1000 }
@ -35,7 +35,7 @@ export function dispose(id) {
const m = Data.get(id) const m = Data.get(id)
Data.remove(id) Data.remove(id)
if(m) { if (m) {
EventHandler.off(document, 'mousemove', m.fnMouseHandler) EventHandler.off(document, 'mousemove', m.fnMouseHandler)
EventHandler.off(document, 'keydown', m.fnKeyHandler) EventHandler.off(document, 'keydown', m.fnKeyHandler)

View File

@ -1,5 +1,5 @@
import { getDescribedElement, getDescribedOwner, hackPopover, isDisabled } from "./utility.js?v=$version" import { getDescribedElement, getDescribedOwner, hackPopover, isDisabled } from "./utility.js"
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
const Popover = { const Popover = {
init(el, config) { init(el, config) {

View File

@ -1,5 +1,5 @@
import "./browser.js?v=$version" import "./browser.js"
import { execute } from "./ajax.js?v=$version" import { execute } from "./ajax.js"
export async function ping(url, invoke, method) { export async function ping(url, invoke, method) {
const data = await getClientInfo(url); const data = await getClientInfo(url);

View File

@ -1,4 +1,4 @@
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export default { export default {
init(id, waitMs) { init(id, waitMs) {

View File

@ -1,4 +1,4 @@
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export default { export default {
drag: (el, start, move, end) => { drag: (el, start, move, end) => {

View File

@ -1,5 +1,5 @@
import { isElement } from "./utility.js?v=$version" import { isElement } from "./utility.js"
import Data from "./data.js?v=$version" import Data from "./data.js"
export function init(id) { export function init(id) {
const fs = {} const fs = {}

View File

@ -1,6 +1,6 @@
import { getClientInfo } from "./client.js?v=$version" import { getClientInfo } from "./client.js"
import Data from "./data.js?v=$version" import Data from "./data.js"
import EventHandler from "./event-handler.js?v=$version"; import EventHandler from "./event-handler.js";
export async function init(id, options) { export async function init(id, options) {
const { invoke, method, interval = 3000, url, connectionId } = options; const { invoke, method, interval = 3000, url, connectionId } = options;

View File

@ -1,4 +1,4 @@
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export default { export default {
composition(id, invoke, callback) { composition(id, invoke, callback) {

View File

@ -1,5 +1,5 @@
import Data from "./data.js?v=$version" import Data from "./data.js"
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export function init(id, invoke, callback) { export function init(id, invoke, callback) {
const resp = { const resp = {

View File

@ -1,5 +1,5 @@
import Data from "./data.js?v=$version" import Data from "./data.js"
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export function init(id) { export function init(id) {
const el = document.getElementById(id) const el = document.getElementById(id)

View File

@ -251,8 +251,8 @@ const addLink = (href, rel = "stylesheet") => {
if (link.length === 0) { if (link.length === 0) {
const css = document.createElement('link') const css = document.createElement('link')
link.push(css) link.push(css)
css.setAttribute('href', href)
css.setAttribute("rel", rel) css.setAttribute("rel", rel)
css.setAttribute('href', href)
document.getElementsByTagName("head")[0].appendChild(css) document.getElementsByTagName("head")[0].appendChild(css)
css.onload = () => { css.onload = () => {
css.setAttribute('loaded', true) css.setAttribute('loaded', true)

View File

@ -1,5 +1,5 @@
import Drag from "./drag.js?v=$version" import Drag from "./drag.js"
import EventHandler from "./event-handler.js?v=$version" import EventHandler from "./event-handler.js"
export default { export default {
init(el, prevList, config) { init(el, prevList, config) {

View File

@ -2,7 +2,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BuildBundlerMinifierPlus" Version="5.3.0" Condition="'$(Configuration)'=='Debug' and '$(TargetFramework)' == 'net8.0'" /> <PackageReference Include="BuildBundlerMinifierPlus" Version="5.3.0" Condition="'$(Configuration)'=='Debug' and '$(TargetFramework)' == 'net8.0'" />
<PackageReference Include="AspNetCore.SassCompiler" Version="1.72.0" Condition="'$(Configuration)'=='Debug' and '$(TargetFramework)' == 'net8.0'" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,6 +2,10 @@
<Import Project="..\Directory.Build.props" /> <Import Project="..\Directory.Build.props" />
<PropertyGroup>
<IsPackable>true</IsPackable>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<RepositoryUrl>https://github.com/dotnetcore/BootstrapBlazor.git</RepositoryUrl> <RepositoryUrl>https://github.com/dotnetcore/BootstrapBlazor.git</RepositoryUrl>
<PackageProjectUrl>https://www.blazor.zone</PackageProjectUrl> <PackageProjectUrl>https://www.blazor.zone</PackageProjectUrl>
@ -10,6 +14,10 @@
<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile> <DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<NoWarn>NETSDK1138</NoWarn> <NoWarn>NETSDK1138</NoWarn>
<NoWarn>CS8002</NoWarn> <NoWarn>CS8002</NoWarn>

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<Version>8.0.0</Version>
</PropertyGroup>
<PropertyGroup>
<PackageTags>Bootstrap Blazor Server UI Components</PackageTags>
<Description>Bootstrap UI components extensions of TagHelper</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BootstrapBlazor" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<Using Include="BootstrapBlazor.Components" />
<Using Include="Microsoft.AspNetCore.Components" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,35 @@
// Copyright (c) Argo Zhang (argo@163.com). 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/
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.WebUtilities;
using System.Security.Cryptography;
namespace BootstrapBlazor.Components;
/// <summary>
/// IWebHostEnvironment 扩展方法
/// </summary>
static class WebHostEnvironmentExtensions
{
public static string? GetVersionHash(this IWebHostEnvironment env, string? href)
{
var ret = "";
if (!string.IsNullOrEmpty(href))
{
var fileInfo = env.WebRootFileProvider.GetFileInfo(href);
using var readStream = fileInfo.CreateReadStream();
#if NET6_0
var length = readStream.Length;
var buffer = new Span<byte>(new byte[length]);
readStream.Read(buffer);
var hash = SHA256.HashData(buffer);
#else
var hash = SHA256.HashData(readStream);
#endif
ret = WebEncoders.Base64UrlEncode(hash);
}
return $"{href}?v={ret}";
}
}

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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/ // Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.AspNetCore.Hosting;
namespace BootstrapBlazor.Components; namespace BootstrapBlazor.Components;
/// <summary> /// <summary>
@ -22,9 +24,8 @@ public partial class Link
[Parameter] [Parameter]
public string? Version { get; set; } public string? Version { get; set; }
[Inject] [Inject, NotNull]
[NotNull] private IWebHostEnvironment? Env { get; set; }
private IVersionService? VersionService { get; set; }
private string GetHref() => $"{Href}?v={Version ?? VersionService.GetVersion()}"; private string GetHref() => $"{Href}?v={Version ?? Env.GetVersionHash(Href)}";
} }

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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/ // Website: https://www.blazor.zone or https://argozhang.github.io/
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.WebUtilities;
namespace BootstrapBlazor.Components; namespace BootstrapBlazor.Components;
/// <summary> /// <summary>
@ -22,9 +25,8 @@ public partial class Script
[Parameter] [Parameter]
public string? Version { get; set; } public string? Version { get; set; }
[Inject] [Inject, NotNull]
[NotNull] private IWebHostEnvironment? Env { get; set; }
private IVersionService? VersionService { get; set; }
private string GetSrc() => $"{Src}?v={Version ?? VersionService.GetVersion()}"; private string GetSrc() => $"{Src}?v={Env.GetVersionHash(Src)}";
} }

Some files were not shown because too many files have changed in this diff Show More