Skip to content

Commit 1918c84

Browse files
committed
2 parents 2fdfb1e + 4bc092d commit 1918c84

File tree

11 files changed

+111
-46
lines changed

11 files changed

+111
-46
lines changed

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,32 @@
2626

2727
<PackageTips Name="BootstrapBlazor.Html2Pdf" />
2828

29+
<p class="code-label">常见问题</p>
30+
31+
<p class="code-quest">1. 本地或者发布后无法使用</p>
32+
<p class="code-answer"><code>BootstrapBlazor.Html2Pdf v9.0.3</code> 后增加了日志输出功能,可以根据日志判断具体问题出现在哪里。比如由于根据当前浏览器版本去下载对应版本的
33+
<code>chrome-headless-shell-win64.zip</code> 安装包</p>
34+
<Pre>info: BootstrapBlazor.Components.DefaultPdfService[0]
35+
Ready to start downloading browser
36+
info: BootstrapBlazor.Components.DefaultPdfService[0]
37+
Browser downloaded successfully. installed browser 138.0.7204.101
38+
info: BootstrapBlazor.Components.DefaultPdfService[0]
39+
Start your browser | Args: --no-sandbox, --disable-setuid-sandbox, --disable-web-security</Pre>
40+
41+
<p class="code-quest">2. 如何手动安装 <code>Debian</code> Linux 系统的 <code>Chrome</code> 浏览器</p>
42+
<Pre>wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
43+
sudo apt install ./google-chrome-stable_current_amd64.deb</Pre>
44+
45+
<p class="code-quest">3. 如何检查 <code>Debian</code> Linux 系统 <code>Chrome</code> 依赖缺失</p>
46+
<ul class="ul-demo">
47+
<li>检查是否可以连接到 Chrome 服务器</li>
48+
<li>检查服务器是否有执行安装包权限</li>
49+
<li>检查是否有依赖缺失</li>
50+
</ul>
51+
52+
<p class="code-quest">4. 部署后是否会反复下载 Chrome 安装包</p>
53+
<p class="code-answer">不会,Html2Pdf 会检查是否存在安装目录安装成功后即不会重复下载安装操作</p>
54+
2955
<DemoBlock Title="@Localizer["Html2PdfElementTitle"]" Introduction="@Localizer["Html2PdfElementIntro"]" Name="Normal">
3056
<section ignore>
3157
<p>@((MarkupString)Localizer["Html2PdfElementDesc"].Value)</p>

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

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,15 @@ private async Task CreateClient()
5454
// 创建 ITcpSocketClient 实例
5555
var client = TcpSocketFactory.GetOrCreate("localhost", 0);
5656

57-
// 设置 FixLengthDataPackageHandler 数据处理器处理数据定长 4 的数据
58-
client.SetDataHandler(new FixLengthDataPackageHandler(4)
57+
// 设置数据适配器 使用 FixLengthDataPackageHandler 数据处理器处理数据定长 4 的数据
58+
var adapter = new DataPackageAdapter
5959
{
60-
// 设置接收数据回调方法
61-
ReceivedCallBack = buffer =>
62-
{
63-
// 内部自动处理粘包分包问题,这里参数 buffer 一定是定长为 4 的业务数据
64-
receivedBuffer = buffer;
65-
return Task.CompletedTask;
66-
}
60+
DataPackageHandler = new FixLengthDataPackageHandler(4)
61+
};
62+
client.SetDataPackageAdapter(adapter, buffer =>
63+
{
64+
// buffer 即是接收到的数据
65+
return ValueTask.CompletedTask;
6766
});
6867

6968
// 连接远端节点 连接成功后自动开始接收数据
@@ -78,8 +77,36 @@ private async Task CreateClient()
7877
<li><code>DelimiterDataPackageHandler</code> <b>分隔符数据处理器</b> 即通讯包以特定一个或一组字节分割</li>
7978
</ul>
8079

81-
<p class="code-label">5. 数据适配器(设计中)</p>
80+
<p class="code-label">5. 数据适配器</p>
8281

8382
<p>在我们实际应用中,接收到数据包后(已经过数据处理器)大多情况下是需要将电文转化为应用中的具体数据类型 <code>Class</code> 或 <code>Struct</code>。将原始数据包转化为类或者结构体的过程由我们的数据适配器来实现</p>
8483

8584
<p>数据适配器设计思路如下</p>
85+
86+
<ol class="ul-demo">
87+
<li>使用 <code>SocketDataConverterAttribute</code> 标签约定通讯数据使用那个转换类型进行转换 指定类型需继承 <code>ISocketDataConverter</code>
88+
接口
89+
</li>
90+
<li>使用 <code>SocketDataPropertyAttribute</code> 标签约定如何转换数据类型 (Property) 属性值</li>
91+
</ol>
92+
93+
<Pre>[SocketDataConverter(Type = typeof(SocketDataConverter&lt;MockEntity&gt;))]
94+
class MockEntity
95+
{
96+
[SocketDataProperty(Type = typeof(byte[]), Offset = 0, Length = 5)]
97+
public byte[]? Header { get; set; }
98+
99+
[SocketDataProperty(Type = typeof(byte[]), Offset = 5, Length = 2)]
100+
public byte[]? Body { get; set; }
101+
102+
[SocketDataProperty(Type = typeof(Foo), Offset = 7, Length = 1, ConverterType = typeof(FooConverter), ConverterParameters = ["test"])]
103+
public string? Value1 { get; set; }
104+
}</Pre>
105+
106+
<Pre>class FooConverter(string name) : ISocketDataPropertyConverter
107+
{
108+
public object? Convert(ReadOnlyMemory&lt;byte&gt; data)
109+
{
110+
return new Foo() { Id = data.Span[0], Name = name };
111+
}
112+
}</Pre>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
</ul>
4242
<p>本示例服务器端模拟了数据分包即响应数据实际是两次写入所以实际接收端是要通过两次接收才能得到一个完整的响应数据包,可通过 <b>数据适配器</b> 来简化接收逻辑。通过切换下方 <b>是否使用数据适配器</b> 控制开关进行测试查看实际数据接收情况。</p>
4343
<ul class="ul-demo">
44-
<li>不使用 <b>数据处理器</b> 要分两次接收才能接收完整</li>
45-
<li>使用 <b>数据处理器</b> 一次即可接收完整数据包</li>
44+
<li>不使用 <b>数据适配器</b> 要分两次接收才能接收完整</li>
45+
<li>使用 <b>数据适配器</b> 一次即可接收完整数据包</li>
4646
</ul>
4747
<Pre>private readonly DataPackageAdapter _dataAdapter = new()
4848
{

src/BootstrapBlazor.Server/Components/Samples/Sockets/Adapters.razor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ protected override void OnInitialized()
4848
});
4949
_client.ReceivedCallBack += OnReceivedAsync;
5050

51-
_dataAdapter.ReceivedCallBack += async Data =>
51+
_dataAdapter.ReceivedCallBack += async data =>
5252
{
5353
// 直接处理接收的数据
54-
await UpdateReceiveLog(Data);
54+
await UpdateReceiveLog(data);
5555
};
5656
}
5757

@@ -104,7 +104,7 @@ private async ValueTask OnReceivedAsync(ReadOnlyMemory<byte> data)
104104

105105
private async Task UpdateReceiveLog(ReadOnlyMemory<byte> data)
106106
{
107-
var payload = System.Text.Encoding.UTF8.GetString(data.Span);
107+
var payload = Encoding.UTF8.GetString(data.Span);
108108
var body = BitConverter.ToString(data.ToArray());
109109

110110
_items.Add(new ConsoleMessageItem

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Name="Normal" ShowCode="false">
1010
<p>通过 <code>SocketDataConverterAttribute</code> 类标签与 <code>SocketDataPropertyAttribute</code>
1111
属性标签可以将通讯数据自动转化为我们系统中需要的业务实体类,示例如下:</p>
12-
<Pre>[SocketDataConverter(Type = typeof(MockEntitySocketDataConverter))]
12+
<Pre>[SocketDataConverter(Type = typeof(SocketDataConverter&lt;MockEntity&gt;))]
1313
class MockEntity
1414
{
1515
[SocketDataProperty(Type = typeof(byte[]), Offset = 0, Length = 5)]
@@ -26,8 +26,7 @@ class MockEntity
2626
}</Pre>
2727
<p class="code-label">1. <code>SocketDataConverter</code> 参数说明:</p>
2828
<ul class="ul-demo">
29-
<li><b>Type</b>: 自定义转换器类型,组件库内置了 <code>SocketDataConverterBase</code> 泛型基类,继承后非常方便扩展出自己的转换器,重载
30-
<code>TryConvertTo</code> 方法调用基类的 <code>Parse</code> 基本就完成了 99% 的工作量,也可以完全自己解析通讯电文到实体类的各个属性上
29+
<li><b>Type</b>: 自定义转换器类型,组件库内置了 <code>SocketDataConverter</code> 泛型类,建议看一下源码非常方便扩展出自己的转换器
3130
</li>
3231
</ul>
3332
<Pre>class MockEntitySocketDataConverter : SocketDataConverterBase&lt;MockEntity&gt;
@@ -96,7 +95,7 @@ class MockEntity
9695
<li><code>SocketDataUInt64LittleEndianConverter</code> 转成 ulong 无符号整形小端读取</li>
9796
</ul>
9897
<p>自定义数据类型转化器示例</p>
99-
<Pre>[SocketDataConverter(Type = typeof(MockEntitySocketDataConverter))]
98+
<Pre>[SocketDataConverter(Type = typeof(SocketDataConverter&lt;MockEntity&gt;))]
10099
class MockEntity
101100
{
102101
[SocketDataProperty(Type = typeof(byte[]), Offset = 0, Length = 5)]
@@ -107,9 +106,8 @@ class MockEntity
107106

108107
[SocketDataProperty(Type = typeof(Foo), Offset = 7, Length = 1, ConverterType = typeof(FooConverter), ConverterParameters = ["test"])]
109108
public string? Value1 { get; set; }
110-
}
111-
112-
class FooConverter(string name) : ISocketDataPropertyConverter
109+
}</Pre>
110+
<Pre>class FooConverter(string name) : ISocketDataPropertyConverter
113111
{
114112
public object? Convert(ReadOnlyMemory&lt;byte&gt; data)
115113
{

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6858,7 +6858,7 @@
68586858
"AttributeChildContent": "Child component",
68596859
"LoadMoreTitle": "LoadMore Component",
68606860
"LoadMoreIntro": "By setting the <code>LoadMore</code> component parameter <code>IsLoading</code> to control the loading state, the <code>OnLoadMoreAsync</code> callback method loads more data",
6861-
"LoadMoreDesc": "In this example, the loading indicator is displayed by setting <code>CanLoading</code> to <code>true</code>, and the <b>No More Data</b> prompt text is displayed by setting it to <code>false</code> after loading is complete. The UI for loading more data can be customized through <code>LoadingTemplate</code>, the UI displayed when there is no more data can be customized through <code>NoMoreTemplate</code>, and the indicator text displayed when there are no more add-ons can be set through the <code>NoMoreText</code> parameter."
6861+
"LoadMoreDesc": "<p>In this example, the loading indicator is displayed by setting <code>CanLoading</code> to <code>true</code>, and the <b>No More Data</b> prompt text is displayed when loading is complete.</p><ul class=\"ul-demo\"><li>Customize the UI for loading more through <code>LoadingTemplate</code></li><li>Customize the UI displayed when there is no more data through <code>NoMoreTemplate</code></li><li>Set the indicator text displayed when there are no more add-ons through the <code>NoMoreText</code> parameter</li></ui>"
68626862
},
68636863
"BootstrapBlazor.Server.Components.Samples.SortableLists": {
68646864
"SortableListTitle": "SortableList",

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4839,7 +4839,7 @@
48394839
"SocketComponents": "Socket 服务",
48404840
"SocketAutoReceive": "自动接收数据",
48414841
"SocketManualReceive": "手动接收数据",
4842-
"DataPackageAdapter": "数据处理器",
4842+
"DataPackageAdapter": "数据适配器",
48434843
"SocketAutoConnect": "自动重连",
48444844
"SocketDataEntity": "通讯数据转实体类",
48454845
"NetworkMonitor": "网络状态 NetworkMonitor"
@@ -6858,7 +6858,7 @@
68586858
"AttributeChildContent": "子组件",
68596859
"LoadMoreTitle": "LoadMore 组件",
68606860
"LoadMoreIntro": "通过设置 <code>LoadMore</code> 组件参数 <code>CanLoading</code> 控制加载状态,<code>OnLoadMoreAsync</code> 回调方法加载更多数据",
6861-
"LoadMoreDesc": "本例中通过设置 <code>CanLoading</code> 为 <code>true</code> 显示加载指示符,加载完成后设置为 <code>false</code> 显示 <b>没有更多数据</b> 提示文本,可以通过 <code>LoadingTemplate</code> 自定义加载更多的 UI通过 <code>NoMoreTemplate</code> 自定义没有更多数据时显示的 UI,可以通过 <code>NoMoreText</code> 参数设置没有更多加载项时显示的指示文本"
6861+
"LoadMoreDesc": "<p>本例中通过设置 <code>CanLoading</code> 为 <code>true</code> 显示加载指示符,加载完成后设置为 <code>false</code> 显示 <b>没有更多数据</b> 提示文本</p><ul class=\"ul-demo\"><li>通过 <code>LoadingTemplate</code> 自定义加载更多的 UI</li><li>通过 <code>NoMoreTemplate</code> 自定义没有更多数据时显示的 UI</li><li>通过 <code>NoMoreText</code> 参数设置没有更多加载项时显示的指示文本</li></ui>"
68626862
},
68636863
"BootstrapBlazor.Server.Components.Samples.SortableLists": {
68646864
"SortableListTitle": "SortableList 拖拽组件",

src/BootstrapBlazor/Components/IntersectionObserver/LoadMore.razor.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
align-items: center;
1010
background-color: var(--bb-intersection-observer-loading-bg);
1111
color: var(--bb-intersection-observer-loading-color);
12-
padding: var(--bb-intersection-observer-loading-padding)
12+
padding: var(--bb-intersection-observer-loading-padding);
13+
margin-bottom: 1px;
1314
}
1415
}

src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverterBase.cs renamed to src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverter.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,27 @@ namespace BootstrapBlazor.Components;
1111
/// Provides a base class for converting socket data into a specified entity type.
1212
/// </summary>
1313
/// <typeparam name="TEntity">The type of entity to convert the socket data into.</typeparam>
14-
public abstract class SocketDataConverterBase<TEntity> : ISocketDataConverter<TEntity>
14+
public class SocketDataConverter<TEntity> : ISocketDataConverter<TEntity>
1515
{
1616
/// <summary>
1717
/// <inheritdoc/>
1818
/// </summary>
1919
/// <param name="data"></param>
2020
/// <param name="entity"></param>
2121
/// <returns></returns>
22-
public abstract bool TryConvertTo(ReadOnlyMemory<byte> data, [NotNullWhen(true)] out TEntity? entity);
22+
public virtual bool TryConvertTo(ReadOnlyMemory<byte> data, [NotNullWhen(true)] out TEntity? entity)
23+
{
24+
var v = CreateEntity();
25+
var ret = Parse(data, v);
26+
entity = ret ? v : default;
27+
return ret;
28+
}
29+
30+
/// <summary>
31+
/// 创建实体实例方法
32+
/// </summary>
33+
/// <returns></returns>
34+
protected virtual TEntity CreateEntity() => Activator.CreateInstance<TEntity>();
2335

2436
/// <summary>
2537
/// 将字节数据转换为指定实体类型的实例。

src/BootstrapBlazor/Services/TcpSocket/SocketClientOptions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace BootstrapBlazor.Components;
1010
/// <summary>
1111
/// Represents configuration options for a socket client, including buffer sizes, timeouts, and endpoints.
1212
/// </summary>
13-
/// <remarks>Use this class to configure various settings for a socket client, such as connection timeouts,
13+
/// <remarks>Use this class to configure various settings for a socket client, such as connection timeouts,
1414
/// buffer sizes, and local or remote endpoints. These options allow fine-tuning of socket behavior to suit specific
1515
/// networking scenarios.</remarks>
1616
public class SocketClientOptions
@@ -49,14 +49,14 @@ public class SocketClientOptions
4949
/// Gets or sets the local endpoint for the socket client. Default value is <see cref="IPAddress.Any"/>
5050
/// </summary>
5151
/// <remarks>This property specifies the local network endpoint that the socket client will bind to when establishing a connection.</remarks>
52-
public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
52+
public IPEndPoint LocalEndPoint { get; set; } = new(IPAddress.Any, 0);
5353

5454
/// <summary>
5555
/// Gets or sets a value indicating whether logging is enabled. Default value is false.
5656
/// </summary>
5757
public bool EnableLog { get; set; }
58-
59-
/// <summary>
58+
59+
/// <summary>
6060
/// Gets or sets a value indicating whether the system should automatically attempt to reconnect after a connection is lost. Default value is false.
6161
/// </summary>
6262
public bool IsAutoReconnect { get; set; }

0 commit comments

Comments
 (0)