Skip to content

Commit e8865d7

Browse files
committed
2 parents dc5c76d + ed2e900 commit e8865d7

File tree

13 files changed

+189
-30
lines changed

13 files changed

+189
-30
lines changed

src/BootstrapBlazor.Server/Components/Samples/AutoCompletes.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
<h4>@Localizer["Description"]</h4>
77

88
<DemoBlock Title="@Localizer["Block1Title"]" Introduction="@Localizer["Block1Intro"]" Name="Normal">
9-
<section ignore>@Localizer["NormalDescription"]</section>
9+
<section ignore>@((MarkupString)Localizer["NormalDescription"].Value)</section>
1010
<div style="width: 200px;">
11-
<AutoComplete Value="@_value" Items="@StaticItems" IsSelectAllTextOnFocus="true"></AutoComplete>
11+
<AutoComplete Value="@_value" Items="@StaticItems" IsSelectAllTextOnFocus="true" IsClearable></AutoComplete>
1212
</div>
1313
</DemoBlock>
1414

src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,68 @@ private IModbusFactory? ModbusFactory { get; set; }</Pre>
6868
<li>输入寄存器 (Input Registers) <code>ReadInputRegistersAsync</code></li>
6969
<li>保持寄存器 (Holding Registers) <code>ReadHoldingRegistersAsync</code> <code>WriteRegisterAsync</code> <code>WriteMultipleRegistersAsync</code></li>
7070
</ul>
71+
72+
<p>Modbus 协议的最大读取/写入数量限制参考自 Modbus Application Protocol Specification V1.1b3:</p>
73+
74+
<ul class="ul-demo">
75+
<li>线圈 (Coils) 最大读取数量: <code>2000</code>, 最大写入数量: <code>1968</code></li>
76+
<li>离散输入 (Discrete Inputs) 最大读取数量: <code>2000</code></li>
77+
<li>输入寄存器 (Input Registers) 最大读取数量: <code>125</code></li>
78+
<li>保持寄存器 (Holding Registers) 最大读取数量: <code>125</code>, 最大写入数量: <code>123</code></li>
79+
</ul>
80+
81+
<p>项目包含 Benchmark 基准测试工程</p>
82+
83+
<Pre>private const int NumberOfTask = 10;
84+
private const int TaskNumberOfClient = 10;
85+
private const int ClientCount = 10;
86+
87+
private async Task InitLongbowModbus()
88+
{
89+
var sc = new ServiceCollection();
90+
sc.AddModbusFactory();
91+
92+
var provider = sc.BuildServiceProvider();
93+
var factory = provider.GetRequiredService&lt;IModbusFactory&gt;();
94+
95+
for (var index = 0; index &lt; ClientCount; index++)
96+
{
97+
var client = factory.GetOrCreateTcpMaster();
98+
await client.ConnectAsync("127.0.0.1", 502);
99+
await client.ReadHoldingRegistersAsync(0x01, 0x00, 100);
100+
101+
_lgbModbusClients.Add(client);
102+
}
103+
}
104+
105+
[Benchmark]
106+
public async Task LongbowModbus()
107+
{
108+
var tasks = _lgbModbusClients.SelectMany(c =>
109+
{
110+
var tasks = new List&lt;Task&gt;();
111+
for (int i = 0; i &lt; TaskNumberOfClient; i++)
112+
{
113+
tasks.Add(Task.Run(async () =&gt;
114+
{
115+
for (int i = 0; i &lt; NumberOfTask; i++)
116+
{
117+
var d = await c.ReadHoldingRegistersAsync(1, 0, 100);
118+
}
119+
}));
120+
}
121+
return tasks;
122+
}).ToList();
123+
124+
await Task.WhenAll(tasks);
125+
}</Pre>
126+
127+
<p>共 10 个 <code>Socket</code> 连接,每个连接 10 个并发任务,每个任务进行 10 次 <code>ReadHoldingRegistersAsync</code> 方法调用,每个方法读取 100 个地址数据</p>
128+
129+
<p>Benchmark 结果如下:</p>
130+
131+
<Pre>| Method | Mean | Error | StdDev | Allocated |
132+
|------------------ |--------:|---------:|---------:|----------:|
133+
| LongbowModbus | 2.458 s | 0.0488 s | 0.1007 s | 2.11 MB |
134+
| NModbus | 4.752 s | 0.1544 s | 0.4552 s | 3.3 MB |
135+
</Pre>

src/BootstrapBlazor.Server/Components/Samples/Sockets/DataEntities.razor

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,16 @@
7575
}
7676
}</Pre>
7777
<p>此处返回值会与参数 <code>Type = typeof(Foo)</code> 做数据合规检查,如果返回值无法转换为指定 <code>Type</code> 时不进行赋值操作,代码逻辑如下</p>
78-
<Pre>var attr = p.GetCustomAttribute&lt;DataPropertyConverterAttribute&gt;(false) ?? GetPropertyConverterAttribute(p);
78+
<Pre>var attr = p.GetCustomAttribute&lt;DataPropertyConverterAttribute&gt;(false);
7979
if (attr is { Type: not null })
8080
{
8181
var value = attr.ConvertTo(data);
8282
var valueType = value?.GetType();
83-
if (p.PropertyType.IsAssignableFrom(valueType))
83+
if (value == null && IsNullable(p.PropertyType))
84+
{
85+
p.SetValue(entity, null);
86+
}
87+
else if (p.PropertyType.IsAssignableFrom(valueType))
8488
{
8589
p.SetValue(entity, value);
8690
}

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,7 @@
21212121
"OnSelectedItemChangedTitle": "OnSelectedItemChanged",
21222122
"OnSelectedItemChangedIntro": "Click the dropdown item or <kbd>Enter</kbd> trigger the callback",
21232123
"OnValueChanged": "Callback for the Value changed",
2124-
"NormalDescription": "In this example, type 123 strings to display the viewing effect, automatically give the component initialization to the auto-prompt dataset, and the dataset does not change",
2124+
"NormalDescription": "In this example, type 123 strings to display the viewing effect, automatically give the component initialization to the auto-prompt dataset, and the dataset does not change. Enable the clear button by setting <code>IsClearable</code>",
21252125
"LikeMatchDescription": "In this example, type the abc string to display the viewing effect and select all matches in the collection that contain abc and have the same case",
21262126
"NoDataTipDescription": "In this example, type 567 strings because the autocomplete information center does not display custom prompt information - <code>the data you want is not found</code>",
21272127
"NoDataTip": "There is nothing",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,7 @@
21212121
"OnSelectedItemChangedTitle": "下拉菜单选选中回调",
21222122
"OnSelectedItemChangedIntro": "点击下拉菜单或者 <kbd>Enter</kbd> 回车时触发此回调方法",
21232123
"OnValueChanged": "Value 改变时回调方法",
2124-
"NormalDescription": "本例中请键入 123 字符串显示查看效果,自动完成组件初始化时给了自动提示数据集并且数据集无变化",
2124+
"NormalDescription": "本例中请键入 123 字符串显示查看效果,自动完成组件初始化时给了自动提示数据集并且数据集无变化,通过设置 <code>IsClearable</code> 开启清空小按钮",
21252125
"LikeMatchDescription": "本例中请键入 123 字符串显示查看效果,自动完成组件初始化时给了自动提示数据集并且数据集无变化",
21262126
"NoDataTipDescription": "本例中请键入 567 字符串由于自动完成信息中心无数据显示自定义提示信息 - <code>没有找到你想要的数据</code>",
21272127
"NoDataTip": "没有找到你想要的数据",

src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{
66
<BootstrapLabel required="@Required" for="@InputId" ShowLabelTooltip="ShowLabelTooltip" Value="@DisplayText"/>
77
}
8-
<div class="auto-complete" id="@Id">
8+
<div class="@ClassString" id="@Id">
99
<input @attributes="AdditionalAttributes" id="@InputId" class="@ClassName" autocomplete="off" type="text"
1010
data-bs-toggle="@ToggleString" data-bs-placement="@PlacementString"
1111
data-bs-offset="@OffsetString" data-bs-custom-class="@CustomClassString"
@@ -15,6 +15,10 @@
1515
placeholder="@PlaceHolder" disabled="@Disabled" @ref="FocusElement"/>
1616
<span class="form-select-append"><i class="@Icon"></i></span>
1717
<span class="form-select-append ac-loading"><i class="@LoadingIcon"></i></span>
18+
@if (GetClearable())
19+
{
20+
<span class="@ClearClassString"><i class="@ClearIcon"></i></span>
21+
}
1822
<RenderTemplate @ref="_dropdown">
1923
@RenderDropdown
2024
</RenderTemplate>

src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ public partial class AutoComplete
6868
[Parameter]
6969
public bool ShowNoDataTip { get; set; } = true;
7070

71+
/// <summary>
72+
/// Gets or sets whether the select component is clearable. Default is false.
73+
/// </summary>
74+
[Parameter]
75+
public bool IsClearable { get; set; }
76+
77+
/// <summary>
78+
/// Gets or sets the right-side clear icon. Default is fa-solid fa-angle-up.
79+
/// </summary>
80+
[Parameter]
81+
[NotNull]
82+
public string? ClearIcon { get; set; }
83+
7184
/// <summary>
7285
/// IStringLocalizer service instance
7386
/// </summary>
@@ -85,6 +98,19 @@ public partial class AutoComplete
8598
[NotNull]
8699
private RenderTemplate? _dropdown = null;
87100

101+
private string? ClassString => CssBuilder.Default("auto-complete")
102+
.AddClass("is-clearable", IsClearable)
103+
.Build();
104+
105+
/// <summary>
106+
/// Gets the clear icon class string.
107+
/// </summary>
108+
private string? ClearClassString => CssBuilder.Default("clear-icon")
109+
.AddClass($"text-{Color.ToDescriptionString()}", Color != Color.None)
110+
.AddClass($"text-success", IsValid.HasValue && IsValid.Value)
111+
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
112+
.Build();
113+
88114
/// <summary>
89115
/// <inheritdoc/>
90116
/// </summary>
@@ -117,6 +143,7 @@ protected override void OnParametersSet()
117143
PlaceHolder ??= Localizer[nameof(PlaceHolder)];
118144
Icon ??= IconTheme.GetIconByKey(ComponentIcons.AutoCompleteIcon);
119145
LoadingIcon ??= IconTheme.GetIconByKey(ComponentIcons.LoadingIcon);
146+
ClearIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectClearIcon);
120147
}
121148

122149
/// <summary>
@@ -125,6 +152,12 @@ protected override void OnParametersSet()
125152
/// <returns></returns>
126153
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, Value);
127154

155+
/// <summary>
156+
/// Gets whether show the clear button.
157+
/// </summary>
158+
/// <returns></returns>
159+
private bool GetClearable() => IsClearable && !IsDisabled;
160+
128161
/// <summary>
129162
/// Callback method when a candidate item is clicked
130163
/// </summary>

src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ export function init(id, invoke) {
133133
EventHandler.on(document, 'click', ac.closePopover);
134134
EventHandler.on(document, 'keyup', ac.keyup);
135135
});
136+
137+
EventHandler.on(el, 'click', '.clear-icon', e => {
138+
input.value = '';
139+
invoke.invokeMethodAsync('TriggerFilter', '');
140+
});
136141
}
137142

138143
const handlerKeyup = (ac, e) => {
@@ -188,7 +193,7 @@ export function dispose(id) {
188193
Data.remove(id)
189194

190195
if (ac) {
191-
const { popover, input, menu } = ac;
196+
const { el, popover, input, menu } = ac;
192197
if (popover) {
193198
Popover.dispose(popover)
194199
if (input) {
@@ -198,6 +203,8 @@ export function dispose(id) {
198203
EventHandler.off(menu, 'click');
199204
EventHandler.off(input, 'keyup');
200205
Input.dispose(input);
206+
207+
EventHandler.off(el, 'click');
201208
}
202209

203210
const { AutoComplete } = window.BootstrapBlazor;

src/BootstrapBlazor/Components/Select/SelectObject.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public partial class SelectObject<TItem>
7979
/// </summary>
8080
private string? ClassName => CssBuilder.Default("select select-object dropdown")
8181
.AddClass("disabled", IsDisabled)
82-
.AddClass("cls", IsClearable)
82+
.AddClass("is-clearable", IsClearable)
8383
.AddClassFromAttributes(AdditionalAttributes)
8484
.Build();
8585

src/BootstrapBlazor/Components/Select/SelectTable.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ namespace BootstrapBlazor.Components;
9696
/// </summary>
9797
private string? ClassName => CssBuilder.Default("select select-table dropdown")
9898
.AddClass("disabled", IsDisabled)
99-
.AddClass("cls", IsClearable)
99+
.AddClass("is-clearable", IsClearable)
100100
.AddClassFromAttributes(AdditionalAttributes)
101101
.Build();
102102

0 commit comments

Comments
 (0)