!38 增加功能:增加分页组件

* fix: 更改 OnPageItemsChanged 为 Action 类型
* refactor: 格式化文档
* Merge branch 'dev' into dev-pagination
* feat: 增加分页信息是否显示功能
* doc: 更新分页组件演示代码
* feat: 每页显示数量改变时回调外部方法
* feat: 分页组件支持外置每页显示数量源
* style: 设置页码组件右侧对齐
* refactor: 格式化选择每页显示数量显示文字
* feat: 增加移动端适配
* feat: 分页组件支持设置每页显示数量
* feat: Select 组件支持设置 Value 属性显示值
* feat: 增加 PaginationItem 组件
* feat: 增加 PaginationClass 属性
* refactor: 分页组件增加每页显示数量设置
This commit is contained in:
Argo 2020-04-12 00:30:40 +08:00
parent 50178130d1
commit f3b49af9af
13 changed files with 322 additions and 173 deletions

View File

@ -1,49 +1,36 @@
@page "/paginations"
<Block Title="分页组件" Introduction="常用设置分页方式" CodeFile="pagination.1.txt">
<div class="form-inline">
<div class="row">
<div class="form-group col-12">
<Pagination Total="10"></Pagination>
</div>
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="5"></Pagination>
</div>
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="8"></Pagination>
</div>
<div class="form-group col-12">
<Pagination Total="4" CurrentPage="8"></Pagination>
</div>
<div class="form-group col-12">
<Pagination Total="5"></Pagination>
</div>
</div>
</div>
</Block>
<h3>Pagination 分页</h3>
<Block Title="分页组件" Introduction="设置分页的大小" CodeFile="pagination.2.txt">
<h4>当数据量过多时,使用分页分解数据。</h4>
<Block Title="基础用法" Introduction="可以通过下拉框选取每页显示数据数量" CodeFile="pagination.1.txt">
<div class="form-inline">
<div class="row">
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="5" Size="Size.Large"></Pagination>
<Pagination PageItems="3" PageItemsSource="@PageItems" TotalCount="30" OnPageClick="@OnPageClick" OnPageItemsChanged="@OnPageItemsChanged"></Pagination>
</div>
</div>
</div>
<Logger @ref="Trace" class="mt-3" />
</Block>
<Block Title="仅显示文本提示" Introduction="只有一页时不显示切换页码组件,仅显示文本提示" CodeFile="pagination.2.txt">
<div class="form-inline">
<div class="row">
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="5" Size="Size.None"></Pagination>
</div>
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="5" Size="Size.Small"></Pagination>
<Pagination PageItems="20" TotalCount="1"></Pagination>
</div>
</div>
</div>
</Block>
<Block Title="分页组件" Introduction="通过List设置禁止分页" CodeFile="pagination.3.txt">
<Block Title="仅显示分页组件" Introduction="不显示文本提示" CodeFile="pagination.3.txt">
<div class="form-inline">
<div class="row">
<div class="form-group col-12">
<Pagination Total="10" CurrentPage="5" Size="Size.Large" DisableList="@disableList"></Pagination>
</div>
<Pagination PageItems="20" TotalCount="100" ShowPaginationInfo="false"></Pagination>
</div>
</div>
</div>
</Block>

View File

@ -9,21 +9,26 @@ namespace BootstrapBlazor.WebConsole.Pages
/// </summary>
public partial class Paginations
{
/// <summary>
///
/// </summary>
protected Logger? Trace { get; set; }
private Logger? Trace { get; set; }
private void OnPageClick(int pageIndex, int pageItems)
{
Trace?.Log($"PageIndex: {pageIndex} PageItems: {pageItems}");
}
private void OnPageItemsChanged(int pageItems)
{
Trace?.Log($"PageItems: {pageItems}");
}
private IEnumerable<int> PageItems => new int[] { 3, 10, 20, 40 };
/// <summary>
///
/// </summary>
List<string> disableList = new List<string>() { "1", "5", "Next" };
/// <summary>
/// 获得属性方法
/// </summary>
/// <returns></returns>
protected IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
{
{
new AttributeItem() {
Name = "Total",
Description = "分页总页数",

View File

@ -1,5 +1 @@
<Pagination Total="10"></Pagination>
<Pagination Total="10" CurrentPage="5"></Pagination>
<Pagination Total="10" CurrentPage="8"></Pagination>
<Pagination Total="4" CurrentPage="8"></Pagination>
<Pagination Total="5"></Pagination>
<Pagination PageItems="3" PageItemsSource="@PageItems" TotalCount="30" />

View File

@ -291,7 +291,7 @@ section {
margin-left: 38px;
}
.content ul li:not(:last-child) {
.content .sidebar-content ul li:not(:last-child) {
padding-bottom: 0.5rem;
}

View File

@ -1,11 +1,50 @@
@namespace BootstrapBlazor.Components
@inherits PaginationBase
<ul @attributes="@AdditionalAttributes" class="@ClassName">
@foreach (string str in GetShowPagination(CurrentPage, Total))
{
var num = str;
var pagestr = "第" + str + "页";
<li class="@GetLiClassName(CurrentPage,num,DisableList.Contains(num)||(CurrentPage==1&&num=="Previous") || (CurrentPage==Total&&num=="Next"))"><a href="javascript:void(0);" class="page-link" aria-label="@pagestr" @onclick="e => OnClick(num)"> @num </a></li>
}
</ul>
<nav class="nav nav-pages" aria-label="分页组件">
<div class="@PaginationBarClass">
<div class="d-inline-block">显示第 <span>@((PageIndex - 1) * PageItems + 1)</span> 到第 <span>@(Math.Min(PageIndex * PageItems, TotalCount))</span> 条记录</div>
<div class="d-none d-sm-inline-block">,总共 <span>@TotalCount</span> 条记录</div>
@if (PageCount > 1)
{
<span>每页显示</span>
<div class="pagination-items d-none d-sm-inline-block">
<Select TItem="string" Value="@PageItemsString" Items="@GetPageItems()" OnSelectedItemChanged="@OnPageItemsSelectItemChanged" />
</div>
<span class="d-sm-none">@PageItems</span>
<span>条记录</span>
}
</div>
<ul class="@PaginationClass">
<li class="page-item">
<a class="page-link" aria-label="上一页" href="#" @onclick:preventDefault @onclick="e => MovePrev(1)">
<i class="fa fa-angle-left"></i>
</a>
</li>
@if (PageCount > 5)
{
<li class="page-item">
<a class="page-link page-link-prev" aria-label="上一页" href="#" @onclick:preventDefault @onclick="e => MovePrev(5)">
<i class="fa fa-ellipsis-h"></i>
</a>
</li>
}
@for (int i = StartPageIndex; i <= EndPageIndex; i++)
{
<PaginationItem PageIndex="@i" Active="PageIndex == i" OnClick="OnPageItemClick" />
}
@if (PageCount > 5)
{
<li class="page-item">
<a class="page-link page-link-next" aria-label="下一页" href="#" @onclick:preventDefault @onclick="e => MoveNext(5)">
<i class="fa fa-ellipsis-h"></i>
</a>
</li>
}
<li class="page-item">
<a class="page-link" aria-label="下一页" href="#" @onclick:preventDefault @onclick="e => MoveNext(1)">
<i class="fa fa-angle-right"></i>
</a>
</li>
</ul>
</nav>

View File

@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
namespace BootstrapBlazor.Components
{
@ -9,132 +11,162 @@ namespace BootstrapBlazor.Components
public abstract class PaginationBase : BootstrapComponentBase
{
/// <summary>
/// 获得 分页样式集合
/// 获得/设置 页码总数
/// </summary>
public int PageCount => (int)Math.Ceiling(TotalCount * 1.0 / PageItems);
/// <summary>
/// 获得 Pagination 样式
/// </summary>
/// <returns></returns>
protected string? ClassName => CssBuilder.Default("pagination")
.AddClass($"pagination-{Size.ToDescriptionString()}", Size != Size.None)
.AddClassFromAttributes(AdditionalAttributes)
protected string? PaginationClass => CssBuilder.Default("pagination")
.AddClass("d-none", PageCount == 1)
.Build();
/// <summary>
/// 获得/设置 Size 大小
/// </summary>
[Parameter] public Size Size { get; set; } = Size.None;
/// <summary>
/// 获得/设置 当前页数
/// PaginationBar 样式
/// </summary>
[Parameter] public int CurrentPage { get; set; } = 1;
/// <returns></returns>
protected string? PaginationBarClass => CssBuilder.Default("pagination-bar")
.AddClass("d-none", !ShowPaginationInfo)
.Build();
/// <summary>
/// 获得/设置 每页大小
/// 获得 PageItems 下拉框显示文字
/// </summary>
[Parameter] public int? PageSize { get; set; }
/// <value></value>
protected string? PageItemsString => $"{PageItems}条/页";
/// <summary>
/// 获得/设置 分页总页数
/// 获得/设置 开始页码
/// </summary>
[Parameter] public int Total { get; set; } = 1;
protected int StartPageIndex { get; set; }
/// <summary>
/// 获得/设置 分页设置要禁止
/// 获得/设置 结束页码
/// </summary>
[Parameter] public List<string> DisableList { get; set; } = new List<string>();
protected int EndPageIndex { get; set; }
/// <summary>
/// 设置点击页
/// 获得/设置 数据总
/// </summary>
protected void OnClick(string SetPage)
[Parameter]
public int TotalCount { get; set; }
/// <summary>
/// 获得/设置 当前页码
/// </summary>
[Parameter]
public int PageIndex { get; set; } = 1;
/// <summary>
/// 获得/设置 每页显示数据数量
/// </summary>
[Parameter]
public int PageItems { get; set; }
/// <summary>
/// 获得/设置 是否显示分页数据汇总信息 默认为 true 显示
/// </summary>
/// <value></value>
[Parameter] public bool ShowPaginationInfo { get; set; } = true;
/// <summary>
/// 获得/设置 每页显示数据数量的外部数据源
/// </summary>
/// <value></value>
[Parameter] public IEnumerable<int>? PageItemsSource { get; set; }
/// <summary>
/// 点击页码时回调方法
/// </summary>
/// <return>第一个参数是当前页码,第二个参数是当前每页设置显示的数据项数量</return>
[Parameter]
public Action<int, int>? OnPageClick { get; set; }
/// <summary>
/// 点击设置每页显示数据数量时回调方法
/// </summary>
[Parameter]
public Action<int>? OnPageItemsChanged { get; set; }
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
if (SetPage == "<<")
{
CurrentPage = CurrentPage - 4 <= 1 ? 1 : CurrentPage - 4;
}
else if (SetPage == ">>")
{
CurrentPage = CurrentPage + 4 >= Total ? Total : CurrentPage + 4;
}
else if (SetPage == "Previous")
{
CurrentPage = CurrentPage == 1 ? 1 : (CurrentPage - 1);
}
else if (SetPage == "Next")
{
CurrentPage = CurrentPage == Total ? Total : (CurrentPage + 1);
}
else
{
CurrentPage = int.Parse(SetPage);
}
base.OnInitialized();
ResetPageItems();
}
/// <summary>
/// 设置显示页数
/// 上一页方法
/// </summary>
/// <param name="CurrentPage"></param>
/// <param name="Total"></param>
/// <returns></returns>
protected List<string> GetShowPagination(int CurrentPage, int Total)
protected void MovePrev(int index)
{
List<string> list = new List<string>();
list.Add("Previous");
if (Total <= 7)
{
for (int i = 1; i <= Total; i++)
{
list.Add(i.ToString());
}
}
else
{
if (CurrentPage - 3 <= 1)
{
for (int i = 1; i <= 6; i++)
{
list.Add(i.ToString());
}
list.Add(">>");
list.Add(Total.ToString());
}
else if (CurrentPage + 3 >= Total)
{
list.Add("1");
list.Add("<<");
for (int i = Total - 5; i <= Total; i++)
{
list.Add(i.ToString());
}
}
else
{
list.Add("1");
list.Add("<<");
for (int i = CurrentPage - 2; i <= CurrentPage + 2; i++)
{
list.Add(i.ToString());
}
list.Add(">>");
list.Add(Total.ToString());
}
}
list.Add("Next");
return list;
var pageIndex = PageIndex > 1 ? Math.Max(1, PageIndex - index) : PageCount;
OnPageItemClick(pageIndex);
}
/// <summary>
/// 获取 分页li样式集合
/// 下一页方法
/// </summary>
/// <param name="CurrentPage"></param>
/// <param name="ShowPagination"></param>
/// <param name="Disabled"></param>
/// <returns></returns>
protected string? GetLiClassName(int CurrentPage,string ShowPagination ,bool Disabled)
protected void MoveNext(int index)
{
return CssBuilder.Default("page-item")
.AddClass("active", CurrentPage.ToString()== ShowPagination)
.AddClass("disabled", Disabled)
.Build();
var pageIndex = PageIndex < PageCount ? Math.Min(PageCount, PageIndex + index) : 1;
OnPageItemClick(pageIndex);
}
/// <summary>
/// 获得页码设置集合
/// </summary>
/// <returns></returns>
protected IEnumerable<SelectedItem> GetPageItems()
{
var pages = PageItemsSource ?? new List<int>() { 20, 40, 80, 100, 200 };
var ret = new List<SelectedItem>();
for (int i = 0; i < pages.Count(); i++)
{
var item = new SelectedItem(pages.ElementAt(i).ToString(), $"{pages.ElementAt(i)}条/页");
ret.Add(item);
if (pages.ElementAt(i) >= TotalCount) break;
}
return ret;
}
private void ResetPageItems()
{
// 计算 分页开始页码与结束页码
StartPageIndex = Math.Max(1, Math.Min(PageCount - 4, Math.Max(1, PageIndex - 2)));
EndPageIndex = Math.Min(PageCount, Math.Max(5, PageIndex + 2));
}
/// <summary>
/// 点击页码时回调方法
/// </summary>
/// <param name="pageIndex"></param>
protected void OnPageItemClick(int pageIndex)
{
PageIndex = pageIndex;
ResetPageItems();
OnPageClick?.Invoke(pageIndex, PageItems);
}
/// <summary>
/// 每页显示数据项数量选项更改时回调方法
/// </summary>
protected void OnPageItemsSelectItemChanged(SelectedItem item)
{
if (int.TryParse(item.Value, out var pageItems))
{
PageItems = pageItems;
PageIndex = 1;
ResetPageItems();
OnPageItemsChanged?.Invoke(PageItems);
}
}
}
}

View File

@ -0,0 +1,5 @@
@namespace BootstrapBlazor.Components
<li class="@ClassName">
<a class="page-link" aria-label="@LabelString" @onclick:preventDefault @onclick="e => OnClick.InvokeAsync(PageIndex)">@PageIndex</a>
</li>

View File

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Components;
namespace BootstrapBlazor.Components
{
/// <summary>
/// PaginationItem 组件
/// </summary>
public partial class PaginationItem
{
private string? ClassName => CssBuilder.Default("page-item")
.AddClass("active", Active)
.Build();
private string? LabelString => $"第 {PageIndex} 页";
/// <summary>
/// 获得/设置 是否 Active 状态
/// </summary>
[Parameter] public bool Active { get; set; }
/// <summary>
/// 获得/设置 页码
/// </summary>
[Parameter] public int PageIndex { get; set; } = 1;
/// <summary>
/// 获得/设置 点击页码时回调方法
/// </summary>
[Parameter] public EventCallback<int> OnClick { get; set; }
}
}

View File

@ -7,7 +7,7 @@
<label class="control-label" for="@InputId">@DisplayText</label>
}
<div @attributes="AdditionalAttributes" id="@Id" data-toggle="lgbSelect" class="@ClassName">
<input type="text" id="@InputId" readonly disabled="@Disabled" class="@InputClassName" data-toggle="dropdown" placeholder="@PlaceHolder" data-original-title="@ErrorMessage" value="@SelectedItem?.Text" @onblur="@OnBlur" />
<input type="text" id="@InputId" readonly disabled="@Disabled" class="@InputClassName" data-toggle="dropdown" placeholder="@PlaceHolder" data-original-title="@ErrorMessage" value="@ValueString" @onblur="@OnBlur" />
<span class="@ArrowClassName"><i class="fa fa-angle-up"></i></span>
<div class="dropdown-menu-arrow"></div>
<div class="dropdown-menu">

View File

@ -72,6 +72,11 @@ namespace BootstrapBlazor.Components
/// </summary>
protected string? InputId => string.IsNullOrEmpty(Id) ? null : $"{Id}_input";
/// <summary>
/// 获得/设置 当前组件值
/// </summary>
protected string? ValueString => SelectedItem?.Text ?? CurrentValueAsString;
/// <summary>
/// 获得/设置 按钮颜色
/// </summary>

View File

@ -7,7 +7,7 @@
<table class="@ClassName">
<thead>
<tr>
@if(ShowCheckbox)
@if (ShowCheckbox)
{
<th class="@CheckboxColumnClass">
<div class="table-cell">
@ -25,7 +25,7 @@
@for (int index = 0; index < Items.Count(); index++)
{
<tr>
@if(ShowCheckbox)
@if (ShowCheckbox)
{
<td>
<div class="table-cell">

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
namespace BootstrapBlazor.Components
@ -27,4 +27,4 @@ namespace BootstrapBlazor.Components
builder.CloseElement();
}
}
}
}

View File

@ -47,6 +47,8 @@ a {
overflow-x: hidden;
padding: 0.25rem 0;
width: 100%;
font-size: inherit;
cursor: pointer;
}
.form-select .dropdown-menu-arrow {
@ -744,23 +746,70 @@ a {
}
/*end slider*/
/*pagination*/
.nav-pages {
justify-content: space-between;
align-items: center;
width: 100%;
}
.pagination {
margin: 0.5rem 0;
flex: 1 1 auto;
justify-content: flex-end;
}
.page-link:focus {
box-shadow: none;
}
.pagination-items {
display: inline-block;
}
.pagination-items .form-select {
width: 100px;
margin: 0 10px;
}
.pagination-items .form-select .dropdown-menu {
min-width: unset;
}
.pagination-items .form-select .form-control {
width: 100%;
}
.page-item {
min-width: 36px;
}
.page-item:hover .page-link-prev .fa-ellipsis-h:before {
content: "\f100";
}
.page-item:hover .page-link-next .fa-ellipsis-h:before {
content: "\f101";
}
/*end pagination*/
/*table*/
.table-wrapper.table-bordered {
border-radius: 4px;
}
.table-bordered th, .table-bordered td {
border: 1px solid #dee2e6;
border-left: 0;
}
.table-bordered th, .table-bordered td {
border: 1px solid #dee2e6;
border-left: 0;
}
.table-bordered th:last-child, .table-bordered td:last-child {
border-right: 0;
}
.table-bordered tr:last-child td {
border-bottom: 0;
}
.table-bordered tr:last-child td {
border-bottom: 0;
}
.table-th-checkbox {
width: 36px;
@ -801,17 +850,17 @@ a {
text-align: left;
}
.table-cell {
padding: 0 10px;
display: flex;
align-items: center;
}
.table-cell {
padding: 0 10px;
display: flex;
align-items: center;
}
.table-striped tbody tr:nth-of-type(odd) {
background-color: #fafafa;
}
.table-striped tbody tr:nth-of-type(odd) {
background-color: #fafafa;
}
.table-striped tbody tr:hover td {
background-color: #f5f7fa;
}
.table-striped tbody tr:hover td {
background-color: #f5f7fa;
}
/*end table*/