Skip to content

Commit bdf1a26

Browse files
committed
Merge branch 'main' into feat-chat-deepseek
2 parents 436e56a + 49a4da0 commit bdf1a26

File tree

6 files changed

+93
-31
lines changed

6 files changed

+93
-31
lines changed

src/BootstrapBlazor.Server/wwwroot/css/devui.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ pre code.hljs {
5454
--bs-btn-xxl-font-size: 1.5rem;
5555
}
5656

57+
.btn-xs {
58+
--bs-btn-padding-y: 0;
59+
--bs-btn-padding-x: 0.45rem;
60+
}
61+
5762
.btn-circle {
5863
--bb-button-circle-width: 35px;
5964
--bb-button-circle-height: 35px;

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.4.12</Version>
4+
<Version>9.5.0</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/Layout/Layout.razor.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,12 @@ public partial class Layout : IHandlerException
417417
/// 获得/设置 Gets or sets a collection of additional assemblies that should be searched for components that can match URIs.
418418
/// </summary>
419419
[Parameter]
420-
[NotNull]
421420
public IEnumerable<Assembly>? AdditionalAssemblies { get; set; }
422421

423422
/// <summary>
424423
/// 获得/设置 鼠标悬停提示文字信息
425424
/// </summary>
426425
[Parameter]
427-
[NotNull]
428426
public string? TooltipText { get; set; }
429427

430428
/// <summary>
@@ -453,7 +451,7 @@ public partial class Layout : IHandlerException
453451
private IStringLocalizer<Layout>? Localizer { get; set; }
454452

455453
private bool _init;
456-
private Tab _tab = default!;
454+
private Tab _tab = null!;
457455

458456
/// <summary>
459457
/// <inheritdoc/>
@@ -483,7 +481,7 @@ protected override async Task OnInitializedAsync()
483481
if (AuthenticationStateTask != null)
484482
{
485483
// wasm 模式下 开启权限必须提供 AdditionalAssemblies 参数
486-
AdditionalAssemblies ??= new[] { Assembly.GetEntryAssembly()! };
484+
AdditionalAssemblies ??= [Assembly.GetEntryAssembly()!];
487485

488486
var url = Navigation.ToBaseRelativePath(Navigation.Uri);
489487
var context = RouteTableFactory.Create(AdditionalAssemblies, url);

src/BootstrapBlazor/Components/Tab/Tab.razor.scss

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@
504504
&:hover {
505505
background-color: var(--bb-tabs-item-hover-bg-color);
506506
}
507-
}
507+
}
508508
}
509509

510510
.btn-fs {
@@ -593,6 +593,30 @@
593593
margin-left: -2rem;
594594
}
595595

596+
&:not(.active) {
597+
&:not(:hover):not(:first-child) {
598+
.tabs-item {
599+
&:before {
600+
content: '';
601+
width: 2px;
602+
background-color: rgba(var(--bs-emphasis-color-rgb), .2);
603+
position: absolute;
604+
left: 0;
605+
top: 8px;
606+
bottom: 10px;
607+
}
608+
}
609+
}
610+
611+
&:hover + .tabs-item-wrap {
612+
.tabs-item {
613+
&:before {
614+
content: none;
615+
}
616+
}
617+
}
618+
}
619+
596620
.tabs-item {
597621
border: none !important;
598622
border-top-left-radius: 10px;

src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,6 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L
385385
var result = rule.GetValidationResult(value, context);
386386
if (result != null && result != ValidationResult.Success)
387387
{
388-
// 查找 resource 资源文件中的 ErrorMessage
389-
var ruleNameSpan = rule.GetType().Name.AsSpan();
390-
var index = ruleNameSpan.IndexOf(attributeSpan, StringComparison.OrdinalIgnoreCase);
391-
var ruleName = ruleNameSpan[..index];
392388
var find = false;
393389
if (!string.IsNullOrEmpty(rule.ErrorMessage))
394390
{
@@ -400,29 +396,36 @@ private void ValidateDataAnnotations(object? value, ValidationContext context, L
400396
}
401397
}
402398

403-
// 通过设置 ErrorMessage 检索
404-
if (!context.ObjectType.Assembly.IsDynamic && !find
405-
&& !string.IsNullOrEmpty(rule.ErrorMessage)
406-
&& LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString(rule.ErrorMessage, out var msg))
399+
if (!context.ObjectType.Assembly.IsDynamic)
407400
{
408-
rule.ErrorMessage = msg;
409-
find = true;
410-
}
401+
if (!find && !string.IsNullOrEmpty(rule.ErrorMessage)
402+
&& LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString(rule.ErrorMessage, out var msg))
403+
{
404+
// 通过设置 ErrorMessage 检索
405+
rule.ErrorMessage = msg;
406+
find = true;
407+
}
411408

412-
// 通过 Attribute 检索
413-
if (!rule.GetType().Assembly.IsDynamic && !find
414-
&& LocalizerFactory.Create(rule.GetType()).TryGetLocalizerString(nameof(rule.ErrorMessage), out msg))
415-
{
416-
rule.ErrorMessage = msg;
417-
find = true;
418-
}
409+
if (!find && LocalizerFactory.Create(rule.GetType()).TryGetLocalizerString(nameof(rule.ErrorMessage), out msg))
410+
{
411+
// 通过 Attribute 检索
412+
rule.ErrorMessage = msg;
413+
find = true;
414+
}
419415

420-
// 通过 字段.规则名称 检索
421-
if (!context.ObjectType.Assembly.IsDynamic && !find
422-
&& LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg))
423-
{
424-
rule.ErrorMessage = msg;
425-
find = true;
416+
if (!find)
417+
{
418+
// 通过 字段.规则名称 检索
419+
// 查找 resource 资源文件中的 ErrorMessage
420+
var ruleNameSpan = rule.GetType().Name.AsSpan();
421+
var index = ruleNameSpan.IndexOf(attributeSpan, StringComparison.OrdinalIgnoreCase);
422+
var ruleName = index == -1 ? ruleNameSpan[..] : ruleNameSpan[..index];
423+
if (LocalizerFactory.Create(context.ObjectType).TryGetLocalizerString($"{memberName}.{ruleName.ToString()}", out msg))
424+
{
425+
rule.ErrorMessage = msg;
426+
find = true;
427+
}
428+
}
426429
}
427430

428431
if (!find)

test/UnitTest/Components/ValidateFormTest.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,27 @@ public async Task Validate_Service_Ok()
566566
var msg = cut.FindComponent<MockInput<string>>().Instance.GetErrorMessage();
567567
Assert.Equal(HasServiceAttribute.Success, msg);
568568
}
569+
570+
[Fact]
571+
public async Task TestService_Ok()
572+
{
573+
// 自定义验证规则没有使用约定 Attribute 结尾单元测试
574+
var foo = new HasService();
575+
var cut = Context.RenderComponent<ValidateForm>(pb =>
576+
{
577+
pb.Add(a => a.Model, foo);
578+
pb.AddChildContent<MockInput<string>>(pb =>
579+
{
580+
pb.Add(a => a.Value, foo.Tag2);
581+
pb.Add(a => a.ValueExpression, Utility.GenerateValueExpression(foo, "Tag2", typeof(string)));
582+
pb.Add(a => a.ValidateRules, [new FormItemValidator(new TestValidateRule())]);
583+
});
584+
});
585+
var form = cut.Find("form");
586+
await cut.InvokeAsync(() => form.Submit());
587+
var msg = cut.FindComponent<MockInput<string>>().Instance.GetErrorMessage();
588+
Assert.Equal("Test", msg);
589+
}
569590

570591
[Fact]
571592
public async Task RequiredValidator_Ok()
@@ -726,7 +747,7 @@ public void ShowAllInvalidResult_Ok()
726747
private class HasServiceAttribute : ValidationAttribute
727748
{
728749
public const string Success = "Has Service";
729-
public const string Error = "No Service";
750+
private const string Error = "No Service";
730751

731752
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
732753
{
@@ -738,10 +759,21 @@ private class HasServiceAttribute : ValidationAttribute
738759
}
739760
}
740761

762+
private class TestValidateRule : ValidationAttribute
763+
{
764+
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
765+
{
766+
return new("Test");
767+
}
768+
}
769+
741770
private class HasService
742771
{
743772
[HasService]
744773
public string? Tag { get; set; }
774+
775+
[TestValidateRule]
776+
public string? Tag2 { get; set; }
745777
}
746778

747779
[MetadataType(typeof(DummyMetadata))]

0 commit comments

Comments
 (0)