[硬核] Bootstrap Blazor Table 综合演示例子

知识点:

1.导入导出
2.分页功能
3.增删改查
4.批量删除
5.批量编辑(审核)
6.列排序与列搜索
7.顶部搜索实现所有列搜索
8.高级搜索实现多条件搜索
9.顶部与刷新与视图列
10.实现文本类型明细行
11.列的统计
12.隐藏列,时间日期列格式化
13.新窗口打开
14.随机数据
15.自由编辑
16.清空数据
17.模板下载

截图

[硬核] Bootstrap Blazor Table 综合演示例子

[硬核] Bootstrap Blazor Table 综合演示例子

[硬核] Bootstrap Blazor Table 综合演示例子

基础工程

表格组件导出 Excel Word Html Pdf

注入FreeSqlDataService服务,支持全数据导出

更新包

<PackageReference Include="BootstrapBlazor" Version="7.2.3-beta03" /> <PackageReference Include="Densen.FreeSql.Extensions.BootstrapBlazor" Version="7.*" /> 

Program.cs 添加代码

using Densen.DataAcces.FreeSql; builder.Services.AddSingleton(typeof(FreeSqlDataService<>)); builder.Services.ConfigureJsonLocalizationOptions(op => {     // 忽略文化信息丢失日志     op.IgnoreLocalizerMissing = true; }); 

Index.razor添加一个 TabItem

Tab 顺便改为懒加载

<Tab IsLazyLoadTabItem="true">      ...     <TabItem Text="综合演示">         <ImpExpIII />     </TabItem> </Tab> 

添加打印预览 Pages_Host.cshtml

< / body > 前加一句

    <script>         function printDiv() {             window.print();         }     </script> 

数据实体类 DataSalesChannels.cs

查看代码
using BootstrapBlazor.Components; using DocumentFormat.OpenXml.Wordprocessing; using FreeSql.DataAnnotations; using Magicodes.ExporterAndImporter.Excel; using OfficeOpenXml.Table; using System.ComponentModel; using System.ComponentModel.DataAnnotations;   namespace b14table.Data;  [ExcelImporter(IsLabelingError = true)] [ExcelExporter(Name = "导入商品中间表", TableStyle = TableStyles.Light10, AutoFitAllColumn = true)] [AutoGenerateClass(Searchable = true, Filterable = true, Sortable = true, ShowTips = true)]  public class SalesChannels {     [AutoGenerateColumn(Ignore = true)]     [Column(IsIdentity = true)]     [DisplayName("序号")]     public int ID { get; set; }      [AutoGenerateColumn(ComponentType = typeof(ColorPicker), Width = 30)]     [DisplayName("级别")]     public string? Background { get; set; }      [AutoGenerateColumn(FormatString = "yyyy-MM-dd")]     [DisplayName("日期")]     public DateTime Date { get; set; }      [Required(ErrorMessage = "{0}不能为空")]     [DisplayName("名称")]     public string? Name { get; set; }      [DisplayName("项目数量")]     public int Projects { get; set; }      [DisplayName("交单数量")]     public int Orders { get; set; }      [DisplayName("结单数量")]     public int Checkouts { get; set; }      // 编辑界面无法显示小数, 以后再思考     [DisplayName("结单率")]     [AutoGenerateColumn(Readonly = true)]     public string? CheckoutRates { get => GetCheckoutRates(Checkouts, Orders); set => checkoutRates = value; }     string? checkoutRates;       [DisplayName("合格数量")]     public int Qualifieds { get; set; }      [DisplayName("合格率")]     [AutoGenerateColumn(Readonly = true)]     public string? QualifiedRates { get => GetQualifiedRates(Qualifieds, Checkouts); set => qualifiedRates = value; }     string? qualifiedRates;      [DisplayName("总价值")]     public int Total { get; set; }      [DisplayName("应收款")]     public int Receivables { get; set; }      [DisplayName("已收款")]     public int Received { get; set; }      [AutoGenerateColumn(FormatString = "HH:mm:ss")]     [DisplayName("修改日期")]     public DateTime ModifiedDate { get; set; } = DateTime.Now;      [AutoGenerateColumn(TextEllipsis = true, Visible = false, ShowTips = true, ComponentType = typeof(Textarea))]     [DisplayName("备注")]     public string? Remark { get; set; }      [AutoGenerateColumn(Visible = false, ComponentType = typeof(BootstrapInput<decimal>), Width = 80)]     [DisplayName("Test1")]     public decimal Test1 { get; set; }      private string GetCheckoutRates(int checkouts, int orders) => orders > 0 ? (checkouts /(double) orders).ToString("P2") : "0%";      private string GetQualifiedRates(int qualifieds, int checkouts) => checkouts > 0 ? (qualifieds / (double)checkouts).ToString("P2") : "0%";   }  

页面 PagesImpExpIII.razor

查看代码
@page "/impexpiii" @using b14table.Data  @using static Blazor100.Service.ImportExportsService  <PageTitle>综合演示</PageTitle>  <InputFile OnChange="OnChange" style="max-width:400px" class="form-control" /> <br />  <Table @ref="list1"        TItem="SalesChannels"        IsPagination="true"        IsStriped="true"        IsBordered="true"        IsDetails="true"        AutoGenerateColumns="true"        ShowSearch="true"        ShowEmpty="true"         SearchMode="SearchMode.Top"        ShowToolbar="true"        ShowExtendButtons="true"        DataService="DataService"        OnQueryAsync="DataService.QueryAsync"        OnSaveAsync="DataService.SaveAsync"        OnDeleteAsync="DataService.DeleteAsync"        DoubleClickToEdit="@DoubleClickToEdit"        IsMultipleSelect="true"        ShowLineNo="true"        IsExcel="@IsExcel"        ShowDetailRow="_ => true"        ShowCardView="true"        ShowColumnList="true"        ShowFooter="true"        ScrollingDialogContent="true"        EditDialogIsDraggable="true"        EditDialogSize="Size.ExtraLarge"        EditDialogShowMaximizeButton="true"        ShowExportButton        OnExportAsync="ExportAsync"        PageItemsSource="new int[] {10, 20, 50, 100, 200, 500, 1000 }">      <SearchTemplate>         <GroupBox Title="搜索">             <div class="row g-3 form-inline">                 <div class="col-12 col-sm-6">                     <BootstrapInput @bind-Value="@context.Name" maxlength="50" ShowLabel="true" />                 </div>                 <div class="col-12 col-sm-6">                     <BootstrapInput @bind-Value="@context.Date" maxlength="500" ShowLabel="true" />                 </div>             </div>         </GroupBox>     </SearchTemplate>            <DetailRowTemplate>         <div>备注: @context.Remark </div>     </DetailRowTemplate>      <TableFooter Context="context1">          <TableFooterCell Text="当前页小计:" colspan="4" />         <TableFooterCell Text="总价值" colspan="3" />         <TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Total)" />          <TableFooterCell Text="应收款" colspan="3" />         <TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Receivables)" />          <TableFooterCell Text="已收款" colspan="3" />         <TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Received)" />      </TableFooter>      <TableToolbarTemplate>         <TableToolbarButton TItem="SalesChannels" Color="Color.Primary" Text="自由编辑" OnClick="@IsExcelToggle" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Warning" Text="随机数据" IsAsync OnClick="@GetDatasAsync" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="导入" IsAsync OnClick="@ImportExcel" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Danger" Text="清空" IsAsync OnClick="EmptyAll" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Success" Text="模板" IsAsync OnClick="Export模板Async" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Success" Text="打印" IsAsync OnClickCallback="@PrintPreview" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="新窗口打开" IsAsync OnClick="@新窗口打开" />         <TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="批量审批" IsAsync OnClickCallback="@批量审批" />     </TableToolbarTemplate>      <ExportButtonDropdownTemplate>         <h6 class="dropdown-header">当前页数据</h6>         <div class="dropdown-item" @onclick="_=>ExportExcelAsync(list1.Rows)">             <i class="fas fa-file-excel"></i>             <span>Excel</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportWordAsync(list1.Rows)">             <i class="fas fa-file-word"></i>             <span>Word</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportHtmlAsync(list1.Rows)">             <i class="fa-brands fa-html5"></i>             <span>Html</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportPDFAsync(list1.Rows)">             <i class="fas fa-file-pdf"></i>             <span>PDF</span>         </div>         <div class="dropdown-divider"></div>         <h6 class="dropdown-header">全部数据</h6>         <div class="dropdown-item" @onclick="_=>ExportExcelAsync(DataService.GetAllItems())">             <i class="fas fa-file-excel"></i>             <span>Excel</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportWordAsync(DataService.GetAllItems())">             <i class="fas fa-file-word"></i>             <span>Word</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportHtmlAsync(DataService.GetAllItems())">             <i class="fa-brands fa-html5"></i>             <span>Html</span>         </div>         <div class="dropdown-item" @onclick="_=>ExportPDFAsync(DataService.GetAllItems())">             <i class="fas fa-file-pdf"></i>             <span>PDF</span>         </div>     </ExportButtonDropdownTemplate> </Table>  

页面代码 PagesImpExpIII.razor

查看代码
using AmeBlazor.Components; using b14table.Data; using Blazor100.Service; using BootstrapBlazor.Components; using Densen.DataAcces.FreeSql; using DocumentFormat.OpenXml.Spreadsheet; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; using Microsoft.JSInterop; using System.Diagnostics.CodeAnalysis; using static Blazor100.Service.ImportExportsService;  namespace b14table.Pages {     public partial class ImpExpIII     {          [Inject]         IWebHostEnvironment? HostEnvironment { get; set; }          [Inject]         [NotNull]         NavigationManager? NavigationManager { get; set; }          [Inject]         [NotNull]         ImportExportsService? ImportExportsService { get; set; }          [Inject]         [NotNull]         ToastService? ToastService { get; set; }          [Inject]         [NotNull]         FreeSqlDataService<SalesChannels>? DataService { get; set; }          [NotNull]         Table<SalesChannels>? list1 { get; set; }          [Parameter] public int Footercolspan1 { get; set; } = 3;          [Parameter] public int Footercolspan2 { get; set; } = 2;          [Parameter] public int Footercolspan3 { get; set; }          [Parameter] public int FootercolspanTotal { get; set; } = 2;          [Parameter] public string? FooterText { get; set; } = "合计:";          [Parameter] public string? FooterText2 { get; set; }          [Parameter] public string? FooterText3 { get; set; }          [Parameter] public string? FooterTotal { get; set; }          /// <summary>         /// 获得/设置 IJSRuntime 实例         /// </summary>         [Inject]         [NotNull]         protected IJSRuntime? JsRuntime { get; set; }         [Parameter] public string? 新窗口打开Url { get; set; } = "https://localhost:7292/";          // 由于使用了FreeSql ORM 数据服务,可以直接取对象         [Inject]         [NotNull]         IFreeSql? fsql { get; set; }          [Inject] ToastService? toastService { get; set; }         [Inject] SwalService? SwalService { get; set; }           public bool IsExcel { get; set; }         public bool DoubleClickToEdit { get; set; } = true;         protected string UploadPath = "";         protected string? uploadstatus;         long maxFileSize = 1024 * 1024 * 15;         string? tempfilename;          private AggregateType Aggregate { get; set; }                  protected async Task GetDatasAsync()         {             var datas = GetDemoDatas();             await fsql.Insert<SalesChannels>().AppendData(datas).ExecuteAffrowsAsync();             await list1!.QueryAsync();         }          protected override async void OnAfterRender(bool firstRender)         {             if (firstRender)             {                 UploadPath = Path.Combine(HostEnvironment!.WebRootPath, "uploads");                 if (!Directory.Exists(UploadPath)) Directory.CreateDirectory(UploadPath);                 await list1!.QueryAsync();             }         }          protected override async Task OnAfterRenderAsync(bool firstRender)         {             if (firstRender)             {                 //懒的人,直接初始化一些数据用用                 var res = fsql.Select<SalesChannels>().Count();                 if (res == 0)                 {                     var datas = GetDemoDatas();                     await fsql.Insert<SalesChannels>().AppendData(datas).ExecuteAffrowsAsync();                     await list1!.QueryAsync();                 }             }         }          public List<SalesChannels> GetDemoDatas()         {              var list = new List<SalesChannels>();             for (int i = 0; i < 100; i++)             {                 try                 {                     var total = Random.Shared.Next(100, 3000);                     list.Add(new SalesChannels()                     {                         ID = i,                         Name = "渠道" + i,                         Date = DateTime.Now,                         Projects = Random.Shared.Next(10, 55),                         Orders = Random.Shared.Next(3, 10),                         Qualifieds = i,                         Total = total,                         Receivables = total - i,                         Received = i,                         Remark= $"{i} 明细行内嵌套另外一个 Table 组件,由于每行都要关联子表数据,出于性能的考虑,此功能采用 懒加载 模式,即点击展开按钮后,再对嵌套 Table 进行数据填充,通过 ShowDetailRow 回调委托可以控制每一行是否显示明细行,本例中通过 Complete 属性来控制是否显示明细行,可通过翻页来测试本功能"                     });                  }                 catch (Exception e)                 {                     System.Console.WriteLine(e.Message);                 }             }             return list;          }          private Task IsExcelToggle()         {             IsExcel = !IsExcel;             DoubleClickToEdit = !IsExcel;             StateHasChanged();             return Task.CompletedTask;         }          public async Task<bool> Export模板Async()         {             await Export();             return true;         }          private async Task<bool> ExportExcelAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Excel);         private async Task<bool> ExportPDFAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Pdf);         private async Task<bool> ExportWordAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Word);         private async Task<bool> ExportHtmlAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Html);          private async Task<bool> ExportAutoAsync(IEnumerable<SalesChannels> items, ExportType exportType = ExportType.Excel)         {             if (items == null || !items.Any())             {                 await ToastService.Error("提示", "无数据可导出");                 return false;             }             var option = new ToastOption()             {                 Category = ToastCategory.Information,                 Title = "提示",                 Content = $"导出正在执行,请稍等片刻...",                 IsAutoHide = false             };             // 弹出 Toast             await ToastService.Show(option);             await Task.Delay(100);               // 开启后台进程进行数据处理             await Export(items?.ToList(), exportType);              // 关闭 option 相关联的弹窗             option.Close();              // 弹窗告知下载完毕             await ToastService.Show(new ToastOption()             {                 Category = ToastCategory.Success,                 Title = "提示",                 Content = $"导出成功,请检查数据",                 IsAutoHide = false             });             return true;          }          private async Task Export(List<SalesChannels>? items = null, ExportType exportType = ExportType.Excel)         {             try             {                 if (items == null || !items.Any())                 {                     ToastService?.Error($"导出", $"{exportType}出错,无数据可导出");                     return;                 }                 var fileName = items == null ? "模板" : typeof(SalesChannels).Name;                 var fullName = Path.Combine(UploadPath, fileName);                 fullName = await ImportExportsService.Export(fullName, items, exportType);                 fileName = (new System.IO.FileInfo(fullName)).Name;                 ToastService?.Success("提示", fileName + "已生成");                  //下载后清除文件                 NavigationManager.NavigateTo($"uploads/{fileName}", true);                 _ = Task.Run(() =>                 {                     Thread.Sleep(50000);                     System.IO.File.Delete(fullName);                 });              }             catch (Exception e)             {                 ToastService?.Error($"导出", $"{exportType}出错,请检查. {e.Message}");             }         }          public async Task<bool> EmptyAll()         {             fsql.Delete<SalesChannels>().Where(a => 1 == 1).ExecuteAffrows();             await ToastService!.Show(new ToastOption()             {                 Category = ToastCategory.Success,                 Title = "提示",                 Content = "已清空数据",             });              await list1!.QueryAsync();             return true;         }         private async Task ImportExcel()         {             if (string.IsNullOrEmpty(tempfilename))             {                 ToastService?.Error("提示", "请正确选择文件上传");                 return;             }             var option = new ToastOption()             {                 Category = ToastCategory.Information,                 Title = "提示",                 Content = "导入文件中,请稍等片刻...",                 IsAutoHide = false             };             // 弹出 Toast             await ToastService!.Show(option);             await Task.Delay(100);               // 开启后台进程进行数据处理             var isSuccess = await MockImportExcel();              // 关闭 option 相关联的弹窗             option.Close();              // 弹窗告知下载完毕             await ToastService.Show(new ToastOption()             {                 Category = isSuccess ? ToastCategory.Success : ToastCategory.Error,                 Title = "提示",                 Content = isSuccess ? "操作成功,请检查数据" : "出现错误,请重试导入或者上传",                 IsAutoHide = false             });              await list1!.QueryAsync();         }         private async Task<bool> MockImportExcel()         {             var items_temp = await ImportExportsService!.ImportFormExcel<SalesChannels>(tempfilename!);             if (items_temp.items == null)             {                 ToastService?.Error("提示", "文件导入失败: " + items_temp.error);                 return false;             }             //items = SmartCombine(items_temp, items).ToList(); 新数据和老数据合并处理,略100字             await fsql.Insert<SalesChannels>().AppendData(items_temp!.items.ToList()).ExecuteAffrowsAsync();             return true;         }          protected async Task OnChange(InputFileChangeEventArgs e)         {             if (e.File == null) return;             tempfilename = Path.Combine(UploadPath, e.File.Name);             await using FileStream fs = new(tempfilename, FileMode.Create);             using var stream = e.File.OpenReadStream(maxFileSize);             await stream.CopyToAsync(fs);              //正式工程此处是回调,简化版必须InvokeAsync一下,自由发挥             _ = Task.Run(async () => await InvokeAsync(async () => await ImportExcel()));          }          /// <summary>         /// 导出数据方法         /// </summary>         /// <param name="Items"></param>         /// <param name="opt"></param>         /// <returns></returns>         protected async Task<bool> ExportAsync(IEnumerable<SalesChannels> Items, QueryPageOptions opt)         {             var ret = await ExportExcelAsync(Items);             return ret;         }          public Task PrintPreview(IEnumerable<SalesChannels> item)         {             //实际工程自己完善js打印             JsRuntime.InvokeVoidAsync("printDiv");             return Task.CompletedTask;         }          private Task 新窗口打开()         {             if (string.IsNullOrEmpty(新窗口打开Url))             {                 ToastService?.Error("提示", "Url为空!");                 return Task.CompletedTask;             }             JsRuntime.NavigateToNewTab(新窗口打开Url);             return Task.CompletedTask;         }          public async Task 批量审批(IEnumerable<SalesChannels> items)         {             items.ToList().ForEach(a =>             {                 a.Checkouts = a.Orders;                 a.Receivables = 0;                 a.Received = a.Total;                 a.ModifiedDate = DateTime.Now;             });             var res = await fsql.Update<SalesChannels>().SetSource(items).ExecuteAffrowsAsync();              await SwalService!.Show(new SwalOption()             {                 Title = res == 0 ? "提示: 操作失败" : "提示: 操作成功"              });            if (res != 0) await list1!.QueryAsync();          }        } }  

预览

[硬核] Bootstrap Blazor Table 综合演示例子

源代码

https://gitee.com/densen2014/Blazor100/tree/master/b04table

https://github.com/densen2014/Blazor100/tree/master/b04table

项目地址

https://gitee.com/LongbowEnterprise/BootstrapBlazor

项目Wiki

https://gitee.com/LongbowEnterprise/BootstrapBlazor/wikis/QuickStart/[硬核] Table 综合演示例子?sort_id=7452536

发表评论

评论已关闭。

相关文章