!781 docs(#I2A2UF): add layout template simulator

* docs: 更新文档增加项目模板链接
* docs: 更新模板模拟器文档
* fix: 修复 Tab 模式下布局不响应问题
* refactor: 优化代码 ClickMenu 更改为委托
* docs: 示例文档增加多 Tab 支持
* refactor: 重构 Layout 组件
This commit is contained in:
Argo 2020-12-20 14:26:24 +08:00
parent 5f06cde5d9
commit 7906eadef8
8 changed files with 131 additions and 185 deletions

View File

@ -1,9 +1,11 @@
@inherits LayoutComponentBase
<Layout SideWidth="0" IsPage="true" IsFullSide="@IsFullSide" IsFixedHeader="@IsFixedHeader" IsFixedFooter="@IsFixedFooter"
ShowFooter="@ShowFooter" ShowGotoTop="true" ShowCollapseBar="true" OnCollapsed="@OnCollapsed" Menus="@Menus">
ShowFooter="@ShowFooter" ShowGotoTop="true" ShowCollapseBar="true" OnCollapsed="@OnCollapsed" Menus="@GetIconSideMenuItems()"
UseTabSet="@UseTabSet" AdditionalAssemblies="new[] { GetType().Assembly }">
<Header>
<span class="ml-3 flex-fill">Bootstrap of Blazor</span>
<Switch @bind-Value="@UseTabSet" OnText="多标签" OffText="单页" OnColor="@Color.Danger" OffColor="@Color.Dark" style="width: 120px;"></Switch>
<img src="_content/BootstrapBlazor.Shared/images/Argo.png" class="layout-avatar-right" />
<span class="ml-3 d-none d-sm-block">超级管理员</span>
</Header>

View File

@ -15,8 +15,6 @@ namespace BootstrapBlazor.Shared.Pages
/// </summary>
public bool IsCollapsed { get; set; }
private IEnumerable<MenuItem> Menus { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
@ -30,27 +28,11 @@ namespace BootstrapBlazor.Shared.Pages
return Task.CompletedTask;
}
private IEnumerable<MenuItem> GetIconSideMenuItems()
private IEnumerable<MenuItem> GetIconSideMenuItems() => new List<MenuItem>
{
var ret = new List<MenuItem>
{
new MenuItem() { Text = "系统设置", IsActive = true, Icon = "fa fa-fw fa-gears" },
new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
};
ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
return ret;
}
new MenuItem() { Text = "返回组件库", Icon = "fa fa-fw fa-home", Url = "layouts" },
new MenuItem() { Text = "布局网页", Icon = "fa fa-fw fa-desktop", Url = "layout-page" },
new MenuItem() { Text = "示例网页", Icon = "fa fa-fw fa-laptop", Url = "layout-demo" }
};
}
}

View File

@ -1,10 +1,8 @@
<div style="@StyleString">
<Alert ShowBar="true">此页面布局未做移动端适配,请在电脑端查看,直接更改调整区域内设置立即生效</Alert>
<h4>整页面级别组件</h4>
<p>整页面级别组件</p>
<p>通过内置组件 <code>Layout</code> 进行整页面布局</p>
<Tips>通过内置组件 <code>Layout</code> 进行整页面布局,可通过 <code>dotnet new bbapp</code> 或者安装 <code>Visual Studio 2019</code> 项目插件选择 <code>Bootstrap Blazor 项目模板</code> 即可自动生成,详细文档请点击 <a href="template" target="_blank">[传送门]</a></Tips>
<div class="page-layout-demo-option">
<p>布局调整</p>
@ -42,7 +40,7 @@
<Pre CodeFile="layout.7.html"></Pre>
</TabItem>
<TabItem Text="页面文件(Demo.razor)">
<Alert>请注意:开发过程中设置 <code>layout</code> 即可继承上面设置的布局,功能页面中仅实现自己功能即可</Alert>
<Tips>请注意:开发过程中设置 <code>layout</code> 即可继承上面设置的布局,功能页面中仅实现自己功能即可</Tips>
<Pre CodeFile="layout.8.html"></Pre>
</TabItem>
</Tab>

View File

@ -144,6 +144,12 @@ namespace BootstrapBlazor.Shared.Shared
Text = "客户端模式 wasm",
Url = "install-wasm"
});
item.AddItem(new DemoMenuItem()
{
Text = "后台模板模拟器",
Url = "layout-page",
IsNew = true
});
item.IsCollapsed = false;
Menus.Add(item);
@ -635,7 +641,8 @@ namespace BootstrapBlazor.Shared.Shared
item.AddItem(new DemoMenuItem()
{
Text = "布局组件 Layout",
Url = "layouts"
Url = "layouts",
IsUpdate = true
});
item.AddItem(new DemoMenuItem()
{

View File

@ -1,35 +1,38 @@
@inherits LayoutComponentBase
@using System.Reflection
@inherits LayoutComponentBase
<Layout SideWidth="0" IsPage="true" IsFullSide="@IsFullSide" IsFixedHeader="@IsFixedHeader" IsFixedFooter="@IsFixedFooter"
ShowFooter="@ShowFooter" ShowGotoTop="true" ShowCollapseBar="true" Menus="@GetIconSideMenuItems()">
<Header>
<span class="ml-3 flex-fill">Bootstrap of Blazor</span>
<img src="_content/BootstrapBlazor.Shared/images/Argo.png" class="layout-avatar-right" />
<span class="ml-3 d-none d-sm-block">超级管理员</span>
</Header>
<Side>
<div class="layout-banner">
<img class="layout-logo" src="_content/BootstrapBlazor.Shared/images/brand.png" />
<div class="layout-title">
<span>演示系统</span>
<CascadingValue Value="this" IsFixed="true">
<Layout SideWidth="0" IsPage="true" IsFullSide="@IsFullSide" IsFixedHeader="@IsFixedHeader" IsFixedFooter="@IsFixedFooter"
ShowFooter="@ShowFooter" ShowGotoTop="true" ShowCollapseBar="true" Menus="@GetIconSideMenuItems()"
UseTabSet="@UseTabSet" AdditionalAssemblies="new[] { GetType().Assembly }">
<Header>
<span class="ml-3 flex-fill">Bootstrap of Blazor</span>
<Switch @bind-Value="@UseTabSet" OnText="多标签" OffText="单页" OnColor="@Color.Danger" OffColor="@Color.Dark" style="width: 120px;"></Switch>
<img src="_content/BootstrapBlazor.Shared/images/Argo.png" class="layout-avatar-right" />
<span class="ml-3 d-none d-sm-block">超级管理员</span>
</Header>
<Side>
<div class="layout-banner">
<img class="layout-logo" src="_content/BootstrapBlazor.Shared/images/brand.png" />
<div class="layout-title">
<span>后台管理</span>
</div>
</div>
</div>
<div class="layout-user">
<img class="layout-avatar" src="_content/BootstrapBlazor.Shared/images/Argo-C.png">
<div class="layout-title">
<span>管理员</span>
<div class="layout-user">
<img class="layout-avatar" src="_content/BootstrapBlazor.Shared/images/Argo-C.png">
<div class="layout-title">
<span>管理员</span>
</div>
<div class="layout-user-state"></div>
</div>
<div class="layout-user-state"></div>
</div>
</Side>
<Main>
<CascadingValue Value="this" IsFixed="true">
</Side>
<Main>
@Body
</CascadingValue>
</Main>
<Footer>
<div class="text-center flex-fill">
<a class="page-layout-demo-footer-link" href="https://gitee.com/LongbowEnterprise/BootstrapAdmin" target="_blank">Bootstrap Admin</a>
</div>
</Footer>
</Layout>
</Main>
<Footer>
<div class="text-center flex-fill">
<a class="page-layout-demo-footer-link" href="https://gitee.com/LongbowEnterprise/BootstrapAdmin" target="_blank">Bootstrap Admin</a>
</div>
</Footer>
</Layout>
</CascadingValue>

View File

@ -42,47 +42,18 @@ namespace BootstrapBlazor.Shared.Shared
[Parameter]
public bool ShowFooter { get; set; } = true;
private bool UseTabSet { get; set; }
/// <summary>
/// 更新组件方法
/// </summary>
public void Update() => StateHasChanged();
private IEnumerable<MenuItem> GetIconSideMenuItems()
private IEnumerable<MenuItem> GetIconSideMenuItems() => new List<MenuItem>
{
var ret = new List<MenuItem>
{
new MenuItem() { Text = "返回组件库", Icon = "fa fa-fw fa-home", Url = "layouts" },
new MenuItem() { Text = "布局网页", Icon = "fa fa-fw fa-desktop", Url = "layout-page" },
new MenuItem() { Text = "示例网页", Icon = "fa fa-fw fa-laptop", Url = "layout-demo" },
new MenuItem() { Text = "系统设置", Icon = "fa fa-fw fa-gears" },
new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
};
ret[3].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
ret[3].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
ret[3].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
ret[3].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
ret[3].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
ret[3].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
ret[3].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
ret[3].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
ret[4].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
ret[4].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
ret[4].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
ret[4].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
ret[4].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
ret[4].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
ret[5].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
ret[5].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
ret[5].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
ret[5].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
ret[5].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
ret[5].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
return ret;
}
new MenuItem() { Text = "返回组件库", Icon = "fa fa-fw fa-home", Url = "layouts" },
new MenuItem() { Text = "布局网页", Icon = "fa fa-fw fa-desktop", Url = "layout-page" },
new MenuItem() { Text = "示例网页", Icon = "fa fa-fw fa-laptop", Url = "layout-demo" }
};
}
}

View File

@ -4,30 +4,11 @@
<section @attributes="AdditionalAttributes" class="@ClassString">
@if (Side == null)
{
<header class="@HeaderClassString">
@Header
</header>
<main class="@MainClassString">
@if (UseTabSet)
{
<CascadingValue Value="this" IsFixed="true">
<Tab ClickTabToNavigator="true" ShowExtendButtons="true" ShowClose="true"></Tab>
</CascadingValue>
}
else
{
@Main
}
</main>
@RenderHeader.Invoke(false)
@RenderMain
@if (ShowFooter)
{
<footer class="@FooterClassString">
@Footer
@if (ShowGotoTop)
{
<GoTop />
}
</footer>
@RenderFooter
}
}
else if (IsFullSide)
@ -36,90 +17,85 @@
@Side
@if (Menus != null)
{
<div class="layout-menu">
<Scroll IsDark="@IsDark">
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" OnClick="@ClickMenu" />
</Scroll>
</div>
@RenderMenu.Invoke(IsFullSide)
}
</aside>
<section class="layout-right">
<header class="@HeaderClassString">
@if (ShowCollapseBar)
{
<a title="" data-toggle="tooltip" data-original-title="@TooltipText" class="@CollapseBarClassString" @onclick="@CollapseMenu">
<i class="fa fa-bars"></i>
</a>
}
@Header
</header>
<main class="@MainClassString">
@if (UseTabSet)
{
<CascadingValue Value="this" IsFixed="true">
<Tab ClickTabToNavigator="true" ShowExtendButtons="true" ShowClose="true"></Tab>
</CascadingValue>
}
else
{
@Main
}
</main>
@RenderHeader.Invoke(ShowCollapseBar)
@RenderMain
@if (ShowFooter)
{
<footer class="@FooterClassString">
@Footer
@if (ShowGotoTop)
{
<GoTop />
}
</footer>
@RenderFooter
}
</section>
}
else
{
<header class="@HeaderClassString">
@if (ShowCollapseBar)
{
<a title="" data-toggle="tooltip" data-original-title="@TooltipText" class="@CollapseBarClassString" @onclick="@CollapseMenu">
<i class="fa fa-bars"></i>
</a>
}
@Header
</header>
@RenderHeader.Invoke(ShowCollapseBar);
<section class="has-sidebar">
<aside class="@SideClassString" style="@SideStyleString">
@Side
@if (Menus != null)
{
<div class="layout-menu">
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" OnClick="@ClickMenu" />
</div>
@RenderMenu.Invoke(IsFullSide)
}
</aside>
<main class="@MainClassString">
@if (UseTabSet)
{
<CascadingValue Value="this" IsFixed="true">
<Tab ClickTabToNavigator="true" ShowExtendButtons="true" ShowClose="true"></Tab>
</CascadingValue>
}
else
{
@Main
}
</main>
@RenderMain
</section>
@if (ShowFooter)
{
<footer class="@FooterClassString">
@Footer
@if (ShowGotoTop)
{
<GoTop />
}
</footer>
@RenderFooter
}
}
</section>
@code {
RenderFragment<bool> RenderHeader => collapse =>
@<header class="@HeaderClassString">
@if (collapse)
{
<a title="" data-toggle="tooltip" data-original-title="@TooltipText" class="@CollapseBarClassString" @onclick="@(EventCallback.Factory.Create<MouseEventArgs>(this, e => CollapseMenu()))">
<i class="fa fa-bars"></i>
</a>
}
@Header
</header>;
RenderFragment<bool> RenderMenu => hasScroll =>
@<div class="layout-menu">
@if (hasScroll)
{
<Scroll>
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" OnClick="@ClickMenu()" />
</Scroll>
}
else
{
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" OnClick="@ClickMenu()" />
}
</div>;
RenderFragment RenderMain =>
@<main class="@MainClassString">
@if (UseTabSet)
{
<CascadingValue Value="this" IsFixed="true">
<Tab ClickTabToNavigator="true" ShowExtendButtons="true" ShowClose="true"
AdditionalAssemblies="@AdditionalAssemblies"></Tab>
</CascadingValue>
}
else
{
@Main
}
</main>;
RenderFragment RenderFooter =>
@<footer class="@FooterClassString">
@Footer
@if (ShowGotoTop)
{
<GoTop />
}
</footer>;
}

View File

@ -12,6 +12,7 @@ using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace BootstrapBlazor.Components
@ -147,6 +148,12 @@ namespace BootstrapBlazor.Components
[Parameter]
public bool UseTabSet { get; set; }
/// <summary>
/// 获得/设置 Gets or sets a collection of additional assemblies that should be searched for components that can match URIs.
/// </summary>
[Parameter]
public IEnumerable<Assembly>? AdditionalAssemblies { get; set; }
/// <summary>
/// 获得/设置 是否固定 Footer 组件
/// </summary>
@ -218,13 +225,13 @@ namespace BootstrapBlazor.Components
/// 点击菜单时回调此方法
/// </summary>
/// <returns></returns>
protected async Task ClickMenu(MenuItem item)
protected Func<MenuItem, Task> ClickMenu() => async item =>
{
// 小屏幕时生效
if (IsSmallScreen && !item.Items.Any()) await CollapseMenu();
if (OnClickMenu != null) await OnClickMenu(item);
}
};
/// <summary>
/// 设置 请求头方法