Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
【新增】可以使用 IMessageService 动态调用 Message 组件 (#126)
Browse files Browse the repository at this point in the history
## 合并请求( Pull Request )
>标题格式:【新增|修复|移除|更新】摘要描述

### 关于本次更新的主要内容
* 【新增】可以使用 IMessageService 动态调用 Message 组件
* 【新增】基于 Message 组件的 Placement 位置的 css 样式
* 【更新】升级 ComponentBuilder 到 1.5 版本
* 【更新】readme 文档

### 本次合并的类型是什么?
- [ ] 缺陷修复(对缺陷的修复,包括紧急修复和一般修复) 
- [x] 功能开发(新功能、特性的开发,之前功能的完善等)
- [ ] 代码风格(包括命名规范、格式、优化代码的写法等)
- [x] 文档更新(仅对当前版本的文档进行增加、完善和更新)
- [ ] 重构(没有新功能,仅对代码的重构、调整)
- [ ] 测试(单元测试、集成测试、性能测试、压力测试等)
- [ ] DevOps (CI/CD、git action 等)
- [ ] 其他,请在下面进行描述:
   > 其他描述写在这里
   
### 关联的 ISSUE 编号
ISSUE 编号:closing #127 

### 合并请求的必要条件
- [x] 必要的单元测试已经完成
- [x] 完成必要的注释,包括参数、方法、属性、类等
- [x] 代码风格必须符合 C# 的代码规范

### 期望参与合并请求评审的成员
@wuxinheng 


### 其他相关信息
<!--如果有,请写明-->

>
**非常感谢您对本项目的贡献,所有的合并请求最终将由作者通过才可以合并成功。并且要求贡献者需要谦虚地对待每一次评审的内容,并且尊重每一位贡献者的回复。良好的规范才能让项目健康的运转,保持利他精神才是我们一直信奉的价值观。**
  • Loading branch information
teacher-zhou authored Oct 7, 2022
2 parents 0549270 + 9fa23b7 commit 9673880
Show file tree
Hide file tree
Showing 17 changed files with 565 additions and 8 deletions.
2 changes: 2 additions & 0 deletions doc/TDesignBlazor.Docs.Shared/App.razor
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
</LayoutView>
</NotFound>
</Router>

<TDesignContainer/>
29 changes: 27 additions & 2 deletions doc/TDesignBlazor.Docs.Shared/Pages/Components/MessagePage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,30 @@
")
</CodeContent>
</Example>
<h2>通过服务调用</h2>
代码建设中...
<Example Title="通过服务调用">
<Description>注入 <code>IMessageService</code> 接口动态调用消息</Description>
<RunContent>
<Button OnClick="@(e=>MessageService.Show(new MessageConfiguration{ Content="这是全局提示"}))">自定义提示</Button>
<Button Theme="Theme.Primary" OnClick="@(e=>MessageService.Info("普通的提示"))">普通</Button>
<Button Theme="Theme.Success" OnClick="@(e=>MessageService.Success("成功的提示"))">成功</Button>
<Button Theme="Theme.Warning" OnClick="@(e=>MessageService.Warning("警告的提示"))">警告</Button>
<Button Theme="Theme.Danger" OnClick="@(e=>MessageService.Danger("失败的提示"))">失败</Button>
<Button OnClick="@(e=>MessageService.Question("有问题的提示"))">疑问</Button>
<Button Theme="Theme.Primary" OnClick="@(e=>MessageService.Loading("系统加载中"))">加载</Button>
</RunContent>
<CodeContent>
@Code.Create(@"
```cs
@inject IMessageService MessageService

MessageService.Info(...)
MessageService.Success(...)
MessageService.Danger(...)
MessageService.Warning(...)
MessageService.Loading(...)
MessageService.Question(...)
```
")
</CodeContent>
</Example>
@inject IMessageService MessageService
22 changes: 22 additions & 0 deletions doc/TDesignBlazor.Docs.Shared/Pages/Startup/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,26 @@
```
builder.Services.AddTDesignBlazor();
```
")

<h3>修改 App.razor </h3>

@Code.Create(@"
```html
<Router AppAssembly=""@typeof(App).Assembly"">
<Found Context=""routeData"">
<RouteView RouteData=""@routeData"" DefaultLayout=""@typeof(MainLayout)"" />
<FocusOnNavigate RouteData=""@routeData"" Selector=""h1"" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout=""@typeof(MainLayout)"">
<p role=""alert"">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

<!--增加组件-->
<TDesignContainer/>
```
")
18 changes: 18 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@
```cs
@using TDesignBlazor
```
- 在 `App.razor` 增加 `TDesignContainer` 组件,用于动态组件的渲染
```html
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
<!--增加组件-->
<TDesignContainer/>
```
## :pencil: 参与贡献
* 如果你有意向参与贡献,请先阅读[贡献指南](./Contributing.md)
Expand Down
21 changes: 21 additions & 0 deletions src/TDesignBlazor/Components/Messages/IMessageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace TDesignBlazor;
/// <summary>
/// 提供全局提示的功能。
/// </summary>
public interface IMessageService : IDisposable
{
/// <summary>
/// 显示指定消息配置的全局提示。
/// </summary>
/// <param name="configuration">执行消息服务的配置。</param>
Task? Show(MessageConfiguration configuration);
/// <summary>
/// 当消息被关闭后时触发的事件。
/// </summary>
event Action? OnClosed;
/// <summary>
/// 当消息正在显示时触发的事件。
/// </summary>

event Func<MessageConfiguration, Task>? OnShowing;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
namespace TDesignBlazor;

/// <summary>
/// 全局提示。
/// 对用户的操作作出轻量的全局反馈。
/// 请使用 <see cref="IMessageService"/> 进行动态调用。
/// </summary>
[CssClass("t-message")]
public class Message : MessageComponentBase
Expand All @@ -22,6 +23,10 @@ public class Message : MessageComponentBase
/// </summary>
public bool Closed { get; private set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="builder"></param>
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
if (Closed)
Expand Down Expand Up @@ -65,17 +70,23 @@ protected override void AddContent(RenderTreeBuilder builder, int sequence)
}, condition: Closable);
}

/// <summary>
/// <inheritdoc/>
/// </summary>
protected override IconName? GetIconByTheme
{
get
{
if (Theme == TDesignBlazor.MessageTheme.Question)
if (Theme == MessageTheme.Question)
{
return IconName.HelpCircleFilled;
}
return base.GetIconByTheme;
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
protected override void OnParametersSet()
{
base.OnParametersSet();
Expand Down
53 changes: 53 additions & 0 deletions src/TDesignBlazor/Components/Messages/MessageConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using OneOf;

namespace TDesignBlazor;

/// <summary>
/// 表示全局消息的配置。
/// </summary>
/// <remarks>该对象用于 <see cref="IMessageService"/> 调用时传值给 <see cref="Message"/> 组件。</remarks>
public class MessageConfiguration
{
internal Guid Key => Guid.NewGuid();
/// <summary>
/// 获取或设置消息提示的内容文本字符串。
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 获取或设置消息提示的图标。
/// </summary>
public object? Icon { get; set; }
/// <summary>
/// 获取或设置消息提示的主题风格。
/// </summary>
public Theme Theme { get; set; } = Theme.Primary;

/// <summary>
/// 获取或设置消息提示具备加载中的状态。
/// </summary>
public bool Loading { get; set; }
/// <summary>
/// 获取或设置消息提示可以被用户关闭。
/// </summary>
public bool Closable { get; set; }

/// <summary>
/// 获取或设置消息提示持续多久自动关闭,单位是毫秒,默认 5 秒,即 5000 毫秒。
/// </summary>
public int? Delay { get; set; } = 3000;

/// <summary>
/// 获取或设置显示的位置。
/// </summary>
public OneOf<Placement, (int offsetX, int offsetY)> Placement { get; set; } = OneOf<Placement, (int offsetX, int offsetY)>.FromT0(TDesignBlazor.Placement.TopRight);

/// <summary>
/// 获取显示的位置。
/// </summary>
/// <returns>class 或 style</returns>
public static (bool classOrStyle, string value) GetPlacement(OneOf<Placement, (int offsetX, int offsetY)> placement)
=> placement.Match(
p => (true, p.GetCssClass()),
value => new(false, $"left:{value.offsetX}px;top:{value.offsetY}")
);
}
114 changes: 114 additions & 0 deletions src/TDesignBlazor/Components/Messages/MessageContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using Microsoft.AspNetCore.Components.Rendering;

using OneOf;

namespace TDesignBlazor;
/// <summary>
/// 用于 <see cref="IMessageService"/> 动态显示 <see cref="Message"/> 组件的容器组件。
/// </summary>
public class MessageContainer : BlazorComponentBase, IDisposable
{
[Inject] IMessageService? MessageService { get; set; }

Dictionary<OneOf<Placement, (int offsetX, int offsetY)>, List<MessageConfiguration>> _messageListDic = new();



/// <inheritdoc/>
protected override void OnInitialized()
{
base.OnInitialized();
MessageService.OnShowing += MessageService_OnShowing;
}

private async Task MessageService_OnShowing(MessageConfiguration configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}

await AddItem(configuration);
await this.Refresh();
}


/// <inheritdoc/>
protected override void AddContent(RenderTreeBuilder builder, int sequence)
{
foreach (var item in _messageListDic)
{
builder.CreateElement(0, "div", content =>
{
foreach (var configuration in item.Value)
{

content.CreateComponent<Message>(sequence + 1, builder => builder.AddContent(0, configuration.Content), new
{
configuration.Icon,
configuration.Loading,
configuration.Closable,
Theme = (Theme?)configuration?.Theme,
});
}
},
HtmlHelper.CreateHtmlAttributes(attributes =>
{
var (classOrStyle, value) = MessageConfiguration.GetPlacement(item.Key);
attributes["class"] = HtmlHelper.CreateCssBuilder().Append("t-message__list").Append(value, classOrStyle);
if (!classOrStyle)
{
attributes["style"] = HtmlHelper.CreateCssBuilder().Append(value);
}
})
);
}
}

private async Task AddItem(MessageConfiguration configuration)
{
var key = configuration.Placement;
if (_messageListDic.ContainsKey(key))
{
_messageListDic[key].Add(configuration);
}
else
{
_messageListDic.Add(key, new() { configuration });
}

await this.Refresh();

await OnTimeoutRemove();

Task OnTimeoutRemove()
{
Timer timer = new(async (state) =>
{
await RemoveItem((MessageConfiguration)state);
}, configuration, configuration.Delay ??= Timeout.Infinite, Timeout.Infinite);
return Task.CompletedTask;
}
}

private Task RemoveItem(MessageConfiguration configuration)
{
var key = configuration.Placement;
if (_messageListDic.ContainsKey(key))
{
_messageListDic[key].Remove(configuration);

if (!_messageListDic[key].Any())
{
_messageListDic.Remove(key);
}
}
return this.Refresh();
}

public void Dispose()
{
MessageService.OnShowing -= MessageService_OnShowing;

}
}
22 changes: 22 additions & 0 deletions src/TDesignBlazor/Components/Messages/MessageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace TDesignBlazor;
internal class MessageService : IMessageService
{
public event Action? OnClosed;
public event Func<MessageConfiguration, Task> OnShowing;
public void Dispose() => OnClosed?.Invoke();

/// <inheritdoc/>
public async Task Show(MessageConfiguration configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}

if (OnShowing is not null)
{
await OnShowing.Invoke(configuration);
}

}
}
Loading

0 comments on commit 9673880

Please sign in to comment.