diff --git a/exclusion.dic b/exclusion.dic
index 8532dbfa4fa..1ad05d9bec0 100644
--- a/exclusion.dic
+++ b/exclusion.dic
@@ -55,3 +55,4 @@ Splittings
Foos
Localizer
onchange
+Render
diff --git a/localization/de.json b/localization/de.json
index b06a7dd6bc5..cbb22d2c10a 100644
--- a/localization/de.json
+++ b/localization/de.json
@@ -230,6 +230,7 @@
"ExportToastTitle": "Daten exportieren",
"ExportToastContent": "Daten exportieren {0}, automatisches Schließen in {1} Sekunden",
"ExportToastInProgressContent": "Daten exportieren, automatisches Schließen in {0} Sekunden",
+ "ExportCsvDropdownItemText": "MS-Csv",
"ExportExcelDropdownItemText": "MS-Excel",
"ExportPdfDropdownItemText": "Pdf",
"PageInfoText": "{0} - {1} Total {2}",
diff --git a/localization/es.json b/localization/es.json
index 99ebbec61db..ce6336ce572 100644
--- a/localization/es.json
+++ b/localization/es.json
@@ -230,6 +230,7 @@
"ExportToastTitle": "Exportar datos",
"ExportToastContent": "Exportar datos {0}, cierre automático en {0} segundos",
"ExportToastInProgressContent": "Exportar datos, cierre automático en {0} segundos",
+ "ExportCsvDropdownItemText": "MS-Csv",
"ExportExcelDropdownItemText": "MS-Excel",
"ExportPdfDropdownItemText": "Pdf",
"PageInfoText": "{0} - {1} Total {2}",
diff --git a/localization/pt.json b/localization/pt.json
index e8aacbb2984..ae88a27804b 100644
--- a/localization/pt.json
+++ b/localization/pt.json
@@ -230,6 +230,7 @@
"ExportToastTitle": "Exportar dados",
"ExportToastContent": "Exportar dados {0}, Fechamento automático em {0} segundos",
"ExportToastInProgressContent": "Exportar dados, Fechamento automático em {0} segundos",
+ "ExportCsvDropdownItemText": "MS-Csv",
"ExportExcelDropdownItemText": "MS-Excel",
"ExportPdfDropdownItemText": "Pdf",
"PageInfoText": "{0} - {1} Total {2}",
diff --git a/localization/th-TH.json b/localization/th-TH.json
index 3f08d9fbe69..88542ac1fb9 100644
--- a/localization/th-TH.json
+++ b/localization/th-TH.json
@@ -1,4 +1,4 @@
-{
+{
"BootstrapBlazor.Components.AutoComplete": {
"NoDataTip": "ไม่มีข้อมูลที่ตรงกัน",
"PlaceHolder": "กรุณากรอก"
@@ -225,6 +225,7 @@
"ExportToastTitle": "ส่งออกข้อมูล",
"ExportToastContent": "ส่งออกข้อมูล {0},{1} ปิดอัตโนมัติหลังจากวินาที",
"ExportToastInProgressContent": "กำลังส่งออกข้อมูล โปรดทราบภายหลัง, {0} ปิดอัตโนมัติหลังจากวินาที",
+ "ExportCsvDropdownItemText": "ไมโครซอฟท์ Csv รูปแบบ",
"ExportExcelDropdownItemText": "ไมโครซอฟท์ Excel รูปแบบ",
"ExportPdfDropdownItemText": "Pdf รูปแบบ",
"PageInfoText": "{0} - {1} ทั้งหมด {2} บทความ",
diff --git a/localization/zh-TW.json b/localization/zh-TW.json
index 7bd84d686a1..56fa9eabde4 100644
--- a/localization/zh-TW.json
+++ b/localization/zh-TW.json
@@ -239,6 +239,7 @@
"ExportToastTitle": "匯出資料",
"ExportToastContent": "匯出資料 {0},{1} 秒後自動關閉",
"ExportToastInProgressContent": "正在匯出資料,請稍後, {0} 秒後自動關閉",
+ "ExportCsvDropdownItemText": "微軟 Csv 格式",
"ExportExcelDropdownItemText": "微軟 Excel 格式",
"ExportPdfDropdownItemText": "Pdf 格式"
},
diff --git a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
index 30ab477da6d..557e9df10b4 100644
--- a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
+++ b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
@@ -42,12 +42,12 @@
@Localizer["TablesExportTips"]:
+@Localizer["TablesExportTips"]:
public void ConfigureServices(IServiceCollection services) { @@ -38,6 +38,24 @@ ++ ++
++ ++ + + + diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesExport.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesExport.razor.cs index 8ac6bf28926..c9059cbea6d 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesExport.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesExport.razor.cs @@ -25,6 +25,7 @@ public partial class TablesExport /// [NotNull] private List ? Items { get; set; } + private static IEnumerable PageItemsSource => new int[] { 4, 10, 20 }; /// @@ -53,7 +54,7 @@ private async Task OnExportAsync(ITableExportDataContext context) // 自定义导出方法 // 通过 context 参数可以自己查询数据进行导出操作 // 本例使用 context 传递来的 Rows/Columns 自定义文件名为 Test.xlsx - var ret = await Exporter.ExportAsync(context.Rows, context.Columns, "Test.xlsx"); + var ret = await TableExport.ExportExcelAsync(context.Rows, context.Columns, "Test.xlsx"); // 返回 true 时自动弹出提示框 return ret; @@ -61,7 +62,7 @@ private async Task OnExportAsync(ITableExportDataContext context) [Inject] [NotNull] - private ITableExcelExport? Exporter { get; set; } + private ITableExport? TableExport { get; set; } [Inject] [NotNull] @@ -124,7 +125,7 @@ private async Task ExcelExportAsync(ITableExportContext context) // 自定义导出模板导出当前页面数据为 Excel 方法 // 使用 BootstrapBlazor 内置服务 ITableExcelExport 实例方法 ExportAsync 进行导出操作 // 导出数据使用 context 传递来的 Rows/Columns 即为当前页数据 - var ret = await Exporter.ExportAsync(context.Rows, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); + var ret = await TableExport.ExportExcelAsync(context.Rows, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); // 返回 true 时自动弹出提示框 await ShowToast(ret); @@ -145,7 +146,7 @@ private async Task ExcelExportAllAsync(ITableExportContext context) var data = Items.Where(filter.GetFilterFunc ()); // 导出符合条件的所有数据 data - var ret = await Exporter.ExportAsync(data, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); + var ret = await TableExport.ExportExcelAsync(data, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); // 返回 true 时自动弹出提示框 await ShowToast(ret); @@ -156,7 +157,7 @@ private async Task CsvExportAsync(ITableExportContext context) // 自定义导出模板导出当前页面数据为 Csv 方法 // 使用 BootstrapBlazor 内置服务 ITableExcelExport 实例方法 ExportCsvAsync 进行导出操作 // 导出数据使用 context 传递来的 Rows/Columns 即为当前页数据 - var ret = await Exporter.ExportCsvAsync(context.Rows, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.csv"); + var ret = await TableExport.ExportCsvAsync(context.Rows, context.Columns, $"Test_{DateTime.Now:yyyyMMddHHmmss}.csv"); // 返回 true 时自动弹出提示框 await ShowToast(ret); diff --git a/src/BootstrapBlazor.Server/Extensions/ServicesExtensions.cs b/src/BootstrapBlazor.Server/Extensions/ServicesExtensions.cs index 73494c670a3..c41437445ff 100644 --- a/src/BootstrapBlazor.Server/Extensions/ServicesExtensions.cs +++ b/src/BootstrapBlazor.Server/Extensions/ServicesExtensions.cs @@ -143,6 +143,7 @@ public static IServiceCollection AddWebSiteServices(this IServiceCollection serv // 增加 Table Excel 导出服务 services.AddBootstrapBlazorTableExcelExport(); + services.AddTransient (); return services; } diff --git a/src/BootstrapBlazor.Server/Locales/en.json b/src/BootstrapBlazor.Server/Locales/en.json index dd302c982f0..725b7707725 100644 --- a/src/BootstrapBlazor.Server/Locales/en.json +++ b/src/BootstrapBlazor.Server/Locales/en.json @@ -5136,6 +5136,8 @@ "TablesExportNote2": "Add Table Excel export service", "TablesExportShowExportButtonTitle": "Table export function", "TablesExportShowExportButtonIntro": "Whether to display the export button by setting the ShowExportButton
property, the default isfalse
", + "TablesExportShowExportCsvButtonTitle": "Export Csv/Pdf Button", + "TablesExportShowExportCsvButtonIntro": "Show/hideCsv/Pdf
button by setShowExportCsvButton=\"true\"
ShowExportPdfButton=\"true\"
", "TablesExportOnExportAsyncTitle": "Custom export method", "TablesExportOnExportAsyncIntro": "You can customize the export method by setting theOnExportAsync
callback delegate method. If you don't set it, the built-in export function of the component will be used.", "TablesExportButtonDropdownTemplateTitle": "Custom export dropdown button", diff --git a/src/BootstrapBlazor.Server/Locales/zh.json b/src/BootstrapBlazor.Server/Locales/zh.json index 6e88057c773..34d5a31fba9 100644 --- a/src/BootstrapBlazor.Server/Locales/zh.json +++ b/src/BootstrapBlazor.Server/Locales/zh.json @@ -5136,6 +5136,8 @@ "TablesExportNote2": "增加 Table Excel 导出服务", "TablesExportShowExportButtonTitle": "表格导出功能", "TablesExportShowExportButtonIntro": "通过设置ShowExportButton=\"true\"
属性是否显示导出按钮,默认为false
", + "TablesExportShowExportCsvButtonTitle": "导出 Csv/Pdf", + "TablesExportShowExportCsvButtonIntro": "通过设置ShowExportCsvButton=\"true\"
ShowExportPdfButton=\"true\"
控制Csv/Pdf
导出按钮", "TablesExportOnExportAsyncTitle": "自定义导出方法", "TablesExportOnExportAsyncIntro": "通过设置OnExportAsync
回调委托方法可自定义导出方法,不设置将使用组件内置导出函数", "TablesExportButtonDropdownTemplateTitle": "自定义导出下拉框按钮", diff --git a/src/BootstrapBlazor.Server/Services/TableDemoDataService.cs b/src/BootstrapBlazor.Server/Services/TableDemoDataService.cs index 0e98c829daf..825d41fc7b7 100644 --- a/src/BootstrapBlazor.Server/Services/TableDemoDataService.cs +++ b/src/BootstrapBlazor.Server/Services/TableDemoDataService.cs @@ -7,17 +7,12 @@ namespace BootstrapBlazor.Server.Services; ////// 演示网站示例数据注入服务实现类 /// -internal class TableDemoDataService: DataServiceBase where TModel : class, new() +class TableDemoDataService (IStringLocalizer localizer) : DataServiceBase where TModel : class, new() { [NotNull] private List ? Items { get; set; } - private IStringLocalizer Localizer { get; set; } - - public TableDemoDataService(IStringLocalizer localizer) - { - Localizer = localizer; - } + private IStringLocalizer Localizer { get; } = localizer; /// /// 查询操作方法 diff --git a/src/BootstrapBlazor.Server/Services/TableExportPdfService.cs b/src/BootstrapBlazor.Server/Services/TableExportPdfService.cs new file mode 100644 index 00000000000..4f243d7f2b5 --- /dev/null +++ b/src/BootstrapBlazor.Server/Services/TableExportPdfService.cs @@ -0,0 +1,46 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Server.Services; + +class TableExportPdfService(IWebHostEnvironment webHostEnvironment, NavigationManager navigationManager, IHtml2Pdf html2Pdf) : ITableExportPdf +{ + private readonly IWebHostEnvironment _webHostEnvironment = webHostEnvironment; + private readonly NavigationManager _navigationManager = navigationManager; + private readonly IHtml2Pdf _html2Pdf = html2Pdf; + + public async Task PdfDataAsync(string content) + { + var url = await GenerateHtmlAsync(content); + + // 生成 Pdf + return await _html2Pdf.PdfDataAsync(url); + } + + public async Task PdfStreamAsync(string content) + { + var url = await GenerateHtmlAsync(content); + + // 生成 Pdf + return await _html2Pdf.PdfStreamAsync(url); + } + + private async Task GenerateHtmlAsync(string content) + { + // 通过 template 模板文件生成网页文件 + var templateFileName = Path.Combine(_webHostEnvironment.WebRootPath, "pdf/template.htm"); + var template = await File.ReadAllTextAsync(templateFileName); + + // 生成静态 html 文件 + var htmlFileName = $"pdf/{Guid.NewGuid()}.html"; + var filePath = Path.Combine(_webHostEnvironment.WebRootPath, htmlFileName); + using var writer = File.CreateText(filePath); + await writer.WriteLineAsync(string.Format(template, content)); + await writer.FlushAsync(); + writer.Close(); + + // 拼接导出文件网址 + return $"{_navigationManager.BaseUri}{htmlFileName}"; + } +} diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index f0c6c5518b5..5b5a5a4c990 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@ - 8.0.5 +8.0.6-beta01 diff --git a/src/BootstrapBlazor/Components/Table/Table.razor b/src/BootstrapBlazor/Components/Table/Table.razor index fbeaaf06758..0dc0278e39a 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor +++ b/src/BootstrapBlazor/Components/Table/Table.razor @@ -125,6 +125,13 @@ } else { + if (ShowExportCsvButton) + { + + + @ExportCsvDropdownItemText ++ } if (ShowExportExcelButton) {diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Localization.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Localization.cs index ae29d4cdf5f..80da61e7b5d 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Localization.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Localization.cs @@ -414,6 +414,7 @@ private void OnInitLocalization() ExportToastTitle ??= Localizer[nameof(ExportToastTitle)]; ExportToastContent ??= Localizer[nameof(ExportToastContent)]; ExportToastInProgressContent ??= Localizer[nameof(ExportToastInProgressContent)]; + ExportCsvDropdownItemText ??= Localizer[nameof(ExportCsvDropdownItemText)]; ExportExcelDropdownItemText ??= Localizer[nameof(ExportExcelDropdownItemText)]; ExportPdfDropdownItemText ??= Localizer[nameof(ExportPdfDropdownItemText)]; CopyColumnTooltipText ??= Localizer[nameof(CopyColumnTooltipText)]; diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs index ec4410916b3..573ba1cbbb0 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Toolbar.cs @@ -63,6 +63,12 @@ public partial class Table[Parameter] public bool ShowExportExcelButton { get; set; } = true; + /// + /// 获得/设置 是否显示 Csv 导出按钮 默认为 false 显示 + /// + [Parameter] + public bool ShowExportCsvButton { get; set; } + ////// 获得/设置 是否显示 Pdf 导出按钮 默认为 false 显示 /// @@ -75,6 +81,12 @@ public partial class Table[Parameter] public string? ExportButtonIcon { get; set; } + /// + /// 获得/设置 内置导出 Csv 按钮图标 + /// + [Parameter] + public string? CsvExportIcon { get; set; } + ////// 获得/设置 内置导出 Excel 按钮图标 /// @@ -117,6 +129,12 @@ public partial class Table[Parameter] public RenderFragment >? ExportButtonDropdownTemplate { get; set; } + /// + /// 获得/设置 内置导出微软 Csv 按钮文本 默认 null 读取资源文件 + /// + [Parameter] + public string? ExportCsvDropdownItemText { get; set; } + ////// 获得/设置 内置导出微软 Excel 按钮文本 默认 null 读取资源文件 /// @@ -374,16 +392,12 @@ public Func? ShowDeleteButtonCallback [Inject] [NotNull] - private ITableExcelExport? ExcelExport { get; set; } - - [Inject] - [NotNull] - private ITablePdfExport? PdfExport { get; set; } + private ITableExport? TableExport { get; set; } /// /// 获得/设置 各列是否显示状态集合 /// - private ListVisibleColumns { get; } = new(); + private List VisibleColumns { get; } = []; /// /// 获得当前可见列集合 @@ -1021,15 +1035,19 @@ private async Task ExecuteExportAsync(Func > callback) private Task ExportAsync() => ExecuteExportAsync(() => OnExportAsync != null ? OnExportAsync(new TableExportDataContext (TableExportType.Unknown, Rows, GetVisibleColumns(), BuildQueryPageOptions())) - : ExcelExport.ExportAsync(Rows, GetVisibleColumns())); + : TableExport.ExportAsync(Rows, GetVisibleColumns())); + + private Task ExportCsvAsync() => ExecuteExportAsync(() => OnExportAsync != null + ? OnExportAsync(new TableExportDataContext (TableExportType.Pdf, Rows, GetVisibleColumns(), BuildQueryPageOptions())) + : TableExport.ExportCsvAsync(Rows, GetVisibleColumns())); private Task ExportPdfAsync() => ExecuteExportAsync(() => OnExportAsync != null ? OnExportAsync(new TableExportDataContext (TableExportType.Pdf, Rows, GetVisibleColumns(), BuildQueryPageOptions())) - : PdfExport.ExportAsync(Rows, GetVisibleColumns())); + : TableExport.ExportPdfAsync(Rows, GetVisibleColumns())); private Task ExportExcelAsync() => ExecuteExportAsync(() => OnExportAsync != null ? OnExportAsync(new TableExportDataContext (TableExportType.Excel, Rows, GetVisibleColumns(), BuildQueryPageOptions())) - : ExcelExport.ExportAsync(Rows, GetVisibleColumns())); + : TableExport.ExportExcelAsync(Rows, GetVisibleColumns())); /// /// 获取当前 Table 选中的所有行数据 diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index a152b971d6f..197bd6ba8cd 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -130,9 +130,9 @@ namespace BootstrapBlazor.Components; private static string? GetColspan(int colspan) => colspan > 1 ? colspan.ToString() : null; - private bool IsShowFooter => ShowFooter && (Rows.Any() || !IsHideFooterWhenNoData); + private bool IsShowFooter => ShowFooter && (Rows.Count > 0 || !IsHideFooterWhenNoData); - private int PageStartIndex => Rows.Any() ? (PageIndex - 1) * PageItems + 1 : 0; + private int PageStartIndex => Rows.Count > 0 ? (PageIndex - 1) * PageItems + 1 : 0; private string? PageInfoLabelString => Localizer[nameof(PageInfoText), PageStartIndex, (PageIndex - 1) * PageItems + Rows.Count, TotalCount]; @@ -187,7 +187,7 @@ namespace BootstrapBlazor.Components; /// /// 明细行集合用于数据懒加载 /// - protected ListExpandRows { get; } = new List (); + protected List ExpandRows { get; } = []; /// /// 获得/设置 组件工作模式为 Excel 模式 默认 false @@ -350,7 +350,7 @@ public void ExpandDetailRow(TItem item) /// /// 明细行集合用于数据懒加载 /// - protected ListDetailRows { get; } = new List (); + protected List DetailRows { get; } = []; /// /// 获得 表头集合 @@ -695,8 +695,9 @@ private void OnInitParameters() RefreshButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableRefreshButtonIcon); CardViewButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableCardViewButtonIcon); ColumnListButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableColumnListButtonIcon); - ExcelExportIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableExcelExportIcon); - PdfExportIcon ??= IconTheme.GetIconByKey(ComponentIcons.TablePdfExportIcon); + CsvExportIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableExportCsvIcon); + ExcelExportIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableExportExcelIcon); + PdfExportIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableExportPdfIcon); SearchButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableSearchButtonIcon); ResetSearchButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableResetSearchButtonIcon); CloseButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableCloseButtonIcon); @@ -845,6 +846,8 @@ protected override async Task OnAfterRenderAsync(bool firstRender) private string? GetTableName(bool hasHeader) => hasHeader ? ClientTableName : null; + private readonly JsonSerializerOptions _serializerOption = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + private async Task ///> ReloadColumnWidth() { IEnumerable ? ret = null; @@ -858,10 +861,7 @@ private async Task > ReloadColumnWidth() var doc = JsonDocument.Parse(jsonData); if (doc.RootElement.TryGetProperty("cols", out var element)) { - ret = element.Deserialize >(new JsonSerializerOptions() - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }); + ret = element.Deserialize >(_serializerOption); } if (doc.RootElement.TryGetProperty("table", out var tableEl) && tableEl.TryGetInt32(out var tableWidth)) { @@ -1106,7 +1106,7 @@ void SetDynamicEditTemplate() var onValueChanged = Utility.GetOnValueChangedInvoke (col.PropertyType); if (DynamicContext.OnValueChanged != null) { - var parameters = col.ComponentParameters?.ToList() ?? new List >(); + var parameters = col.ComponentParameters?.ToList() ?? []; parameters.Add(new(nameof(ValidateBase .OnValueChanged), onValueChanged.Invoke(d, col, (model, column, val) => DynamicContext.OnValueChanged(model, column, val)))); col.ComponentParameters = parameters; } @@ -1134,7 +1134,7 @@ void SetEditTemplate() /// /// 获得 过滤集合 /// - public DictionaryFilters { get; } = new(); + public Dictionary Filters { get; } = []; #endregion private async ValueTask > LoadItems(ItemsProviderRequest request) @@ -1165,7 +1165,7 @@ private Func TriggerDoubleClickCell(ITableColumn col, TItem item) => async .AddClass("is-dbcell", trigger) .Build(); - private bool IsShowEmpty => ShowEmpty && !Rows.Any(); + private bool IsShowEmpty => ShowEmpty && Rows.Count == 0; private int GetColumnCount() { @@ -1224,7 +1224,7 @@ public async Task ResetFilters() /// 返回 true 时按钮禁用 /// - private bool GetDeleteButtonStatus() => ShowAddForm || AddInCell || !SelectedRows.Any(); + private bool GetDeleteButtonStatus() => ShowAddForm || AddInCell || SelectedRows.Count == 0; private async Task InvokeItemsChanged() { diff --git a/src/BootstrapBlazor/Enums/ComponentIcons.cs b/src/BootstrapBlazor/Enums/ComponentIcons.cs index 61b74192978..dd22c583ec4 100644 --- a/src/BootstrapBlazor/Enums/ComponentIcons.cs +++ b/src/BootstrapBlazor/Enums/ComponentIcons.cs @@ -555,14 +555,19 @@ public enum ComponentIcons TableColumnListButtonIcon, /// - /// Table 组件 ExcelExportIcon 属性图标 + /// Table 组件 ExportExcelIcon 属性图标 /// - TableExcelExportIcon, + TableExportExcelIcon, ///- /// Table 组件 PdfExportIcon 属性图标 + /// Table 组件 ExportCsvIcon 属性图标 /// - TablePdfExportIcon, + TableExportCsvIcon, + + ///+ /// Table 组件 ExportPdfIcon 属性图标 + /// + TableExportPdfIcon, ////// Table 组件 SearchButtonIcon 属性图标 diff --git a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs index 983b5c8c9c0..9784b9a7d73 100644 --- a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs +++ b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs @@ -37,9 +37,6 @@ public static IServiceCollection AddBootstrapBlazor(this IServiceCollection serv services.TryAddSingleton (); services.TryAddSingleton(typeof(IDispatchService<>), typeof(DefaultDispatchService<>)); - services.TryAddTransient (); - services.TryAddTransient (); - services.TryAddScoped(typeof(IDataService<>), typeof(NullDataService<>)); services.TryAddScoped (); services.TryAddScoped (); @@ -63,6 +60,9 @@ public static IServiceCollection AddBootstrapBlazor(this IServiceCollection serv services.AddScoped (); services.AddScoped (); + services.TryAddTransient (); + services.TryAddTransient (); + services.ConfigureBootstrapBlazorOption(configureOptions); services.ConfigureIPLocatorOption(); diff --git a/src/BootstrapBlazor/Locales/en.json b/src/BootstrapBlazor/Locales/en.json index 05ac3fb77b9..9c6d878dcb5 100644 --- a/src/BootstrapBlazor/Locales/en.json +++ b/src/BootstrapBlazor/Locales/en.json @@ -225,6 +225,7 @@ "ExportToastTitle": "Export", "ExportToastContent": "Export data {0}, auto close after {1}s", "ExportToastInProgressContent": "Exporting data, please wait a moment, auto close after {0}s", + "ExportCsvDropdownItemText": "MS-Csv", "ExportExcelDropdownItemText": "MS-Excel", "ExportPdfDropdownItemText": "Pdf", "PageInfoText": "{0} - {1} Total {2}", diff --git a/src/BootstrapBlazor/Locales/zh.json b/src/BootstrapBlazor/Locales/zh.json index 5ed28328aec..9a0a016ad85 100644 --- a/src/BootstrapBlazor/Locales/zh.json +++ b/src/BootstrapBlazor/Locales/zh.json @@ -225,6 +225,7 @@ "ExportToastTitle": "导出数据", "ExportToastContent": "导出数据 {0},{1} 秒后自动关闭", "ExportToastInProgressContent": "正在导出数据,请稍后, {0} 秒后自动关闭", + "ExportCsvDropdownItemText": "微软 Csv 格式", "ExportExcelDropdownItemText": "微软 Excel 格式", "ExportPdfDropdownItemText": "Pdf 格式", "PageInfoText": "{0} - {1} 共 {2} 条", diff --git a/src/BootstrapBlazor/Options/IconThemeOptions.cs b/src/BootstrapBlazor/Options/IconThemeOptions.cs index 914b3dedbc2..39fba748566 100644 --- a/src/BootstrapBlazor/Options/IconThemeOptions.cs +++ b/src/BootstrapBlazor/Options/IconThemeOptions.cs @@ -165,8 +165,9 @@ public IconThemeOptions() { ComponentIcons.TableRefreshButtonIcon, "fa-solid fa-arrows-rotate" }, { ComponentIcons.TableCardViewButtonIcon, "fa-solid fa-bars" }, { ComponentIcons.TableColumnListButtonIcon, "fa-solid fa-table-list" }, - { ComponentIcons.TableExcelExportIcon, "fa-regular fa-file-excel" }, - { ComponentIcons.TablePdfExportIcon, "fa-regular fa-file-pdf" }, + { ComponentIcons.TableExportCsvIcon, "fa-solid fa-fw fa-file-csv" }, + { ComponentIcons.TableExportExcelIcon, "fa-solid fa-fw fa-file-excel" }, + { ComponentIcons.TableExportPdfIcon, "fa-solid fa-fw fa-file-pdf" }, { ComponentIcons.TableSearchButtonIcon, "fa-solid fa-magnifying-glass" }, { ComponentIcons.TableResetSearchButtonIcon, "fa-regular fa-trash-can" }, { ComponentIcons.TableCloseButtonIcon, "fa-solid fa-xmark" }, diff --git a/src/BootstrapBlazor/Services/ComponentHtmlRenderer.cs b/src/BootstrapBlazor/Services/ComponentHtmlRenderer.cs index 58732b792ff..42e9b905e47 100644 --- a/src/BootstrapBlazor/Services/ComponentHtmlRenderer.cs +++ b/src/BootstrapBlazor/Services/ComponentHtmlRenderer.cs @@ -9,9 +9,9 @@ namespace BootstrapBlazor.Components; class ComponentHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : IComponentHtmlRenderer { - private IServiceProvider ServiceProvider { get; set; } = serviceProvider; + private readonly IServiceProvider _serviceProvider = serviceProvider; - private ILoggerFactory LoggerFactory { get; set; } = loggerFactory; + private readonly ILoggerFactory _loggerFactory = loggerFactory; /// /// @@ -21,7 +21,7 @@ class ComponentHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory log /// public async Task RenderAsync (IDictionary ? parameters = null) where TComponent : IComponent { - using var htmlRenderer = new HtmlRenderer(ServiceProvider, LoggerFactory); + using var htmlRenderer = new HtmlRenderer(_serviceProvider, _loggerFactory); var html = await htmlRenderer.Dispatcher.InvokeAsync(async () => { parameters ??= new Dictionary (); @@ -40,7 +40,7 @@ public async Task RenderAsync (IDictionary ? /// public async Task RenderAsync(Type componentType, IDictionary ? parameters = null) { - using var htmlRenderer = new HtmlRenderer(ServiceProvider, LoggerFactory); + using var htmlRenderer = new HtmlRenderer(_serviceProvider, _loggerFactory); var html = await htmlRenderer.Dispatcher.InvokeAsync(async () => { parameters ??= new Dictionary (); diff --git a/src/BootstrapBlazor/Services/DefaultIconTheme.cs b/src/BootstrapBlazor/Services/DefaultIconTheme.cs index b1ee1c04245..954534a968d 100644 --- a/src/BootstrapBlazor/Services/DefaultIconTheme.cs +++ b/src/BootstrapBlazor/Services/DefaultIconTheme.cs @@ -4,18 +4,9 @@ namespace BootstrapBlazor.Components; -internal class DefaultIconTheme : IIconTheme +class DefaultIconTheme(IOptions options) : IIconTheme { - private IOptions Options { get; set; } - - /// - /// - /// - /// - public DefaultIconTheme(IOptionsoptions) - { - Options = options; - } + private readonly IOptions _options = options; /// /// + ///@@ -23,9 +14,9 @@ public DefaultIconTheme(IOptions options) /// public Dictionary GetIcons() { - if (!Options.Value.Icons.TryGetValue(Options.Value.ThemeKey, out var icons)) + if (!_options.Value.Icons.TryGetValue(_options.Value.ThemeKey, out var icons)) { - icons = new Dictionary (); + icons = []; } return icons; } diff --git a/src/BootstrapBlazor/Services/DefaultPdfExport.cs b/src/BootstrapBlazor/Services/DefaultPdfExport.cs deleted file mode 100644 index 2356d3f64b6..00000000000 --- a/src/BootstrapBlazor/Services/DefaultPdfExport.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// Website: https://www.blazor.zone or https://argozhang.github.io/ - -namespace BootstrapBlazor.Components; - -class DefaultPdfExport : ITablePdfExport -{ - /// - /// - ///- /// - /// - /// - /// - /// - public Task ExportAsync (IEnumerable items, IEnumerable ? cols = null, string? fileName = null) where TItem : class - { - return Task.FromResult(false); - } -} diff --git a/src/BootstrapBlazor/Services/DefaultExcelExport.cs b/src/BootstrapBlazor/Services/DefaultTableExport.cs similarity index 57% rename from src/BootstrapBlazor/Services/DefaultExcelExport.cs rename to src/BootstrapBlazor/Services/DefaultTableExport.cs index 34fc31d63fb..9a1626eaa3f 100644 --- a/src/BootstrapBlazor/Services/DefaultExcelExport.cs +++ b/src/BootstrapBlazor/Services/DefaultTableExport.cs @@ -4,7 +4,7 @@ namespace BootstrapBlazor.Components; -class DefaultExcelExport : ITableExcelExport +class DefaultTableExport : ITableExport { /// /// + ///@@ -15,6 +15,15 @@ public Task ExportAsync (IEnumerable items, IEnumerable + /// + /// + public Task ExportExcelAsync (IEnumerable items, IEnumerable ? cols = null, string? fileName = null) + { + return Task.FromResult(false); + } + /// /// @@ -27,4 +36,17 @@ public Task/// ExportCsvAsync (IEnumerable items, IEnumerable + /// + /// + /// + /// + /// + /// + public Task ExportPdfAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null) + { + return Task.FromResult(false); + } } diff --git a/src/BootstrapBlazor/Services/DefaultTableExportPdf.cs b/src/BootstrapBlazor/Services/DefaultTableExportPdf.cs new file mode 100644 index 00000000000..e2c4380e374 --- /dev/null +++ b/src/BootstrapBlazor/Services/DefaultTableExportPdf.cs @@ -0,0 +1,25 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Components; + +[ExcludeFromCodeCoverage] +class DefaultTableExportPdf : ITableExportPdf +{ + /// + /// + /// + ///+ /// + /// + public Task PdfDataAsync(string content) => Task.FromResult(Array.Empty ()); + + /// + /// + /// + ///+ /// + /// + public Task PdfStreamAsync(string content) => Task.FromResult(Stream.Null); +} diff --git a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/IHtml2Pdf.cs b/src/BootstrapBlazor/Services/IHtml2Pdf.cs similarity index 63% rename from src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/IHtml2Pdf.cs rename to src/BootstrapBlazor/Services/IHtml2Pdf.cs index 54b7bc833fe..b1f7d8ab450 100644 --- a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/IHtml2Pdf.cs +++ b/src/BootstrapBlazor/Services/IHtml2Pdf.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Website: https://www.blazor.zone or https://argozhang.github.io/ -using PuppeteerSharp; - namespace BootstrapBlazor.Components; /// @@ -15,13 +13,11 @@ public interface IHtml2Pdf /// Export method /// /// url - /// the instance of PdfOptions - TaskExportDataAsync(string url, PdfOptions? options = null); + Task PdfDataAsync(string url); /// - /// 导出流 + /// Export method /// /// url - /// the instance of PdfOptions - TaskExportStreamAsync(string url, PdfOptions? options = null); + Task PdfStreamAsync(string url); } diff --git a/src/BootstrapBlazor/Services/ITableExcelExport.cs b/src/BootstrapBlazor/Services/ITableExcelExport.cs index 662010c9421..bbe5e14be4e 100644 --- a/src/BootstrapBlazor/Services/ITableExcelExport.cs +++ b/src/BootstrapBlazor/Services/ITableExcelExport.cs @@ -7,6 +7,7 @@ namespace BootstrapBlazor.Components; /// /// Table 组件 Excel 导出接口 /// +[Obsolete("已过期,请使用 ITableExport 代替 Please use ITableExport instead")] public interface ITableExcelExport { ///@@ -24,4 +25,12 @@ public interface ITableExcelExport /// 当前可见列数据集合 默认 null 导出全部列 /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx Task ExportCsvAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); + + /// + /// 导出 Pdf 方法 + /// + /// 导出数据集合 + /// 当前可见列数据集合 默认 null 导出全部列 + /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx + TaskExportPdfAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); } diff --git a/src/BootstrapBlazor/Services/ITableExport.cs b/src/BootstrapBlazor/Services/ITableExport.cs new file mode 100644 index 00000000000..71a0ca4116f --- /dev/null +++ b/src/BootstrapBlazor/Services/ITableExport.cs @@ -0,0 +1,43 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Components; + +/// +/// Table 组件 Excel 导出接口 +/// +public interface ITableExport +{ + ///+ /// 导出 方法 + /// + /// 导出数据集合 + /// 当前可见列数据集合 默认 null 导出全部列 + /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx + TaskExportAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); + + /// + /// 导出 Excel 方法 + /// + /// 导出数据集合 + /// 当前可见列数据集合 默认 null 导出全部列 + /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx + TaskExportExcelAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); + + /// + /// 导出 Csv 方法 + /// + /// 导出数据集合 + /// 当前可见列数据集合 默认 null 导出全部列 + /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx + TaskExportCsvAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); + + /// + /// 导出 Pdf 方法 + /// + /// 导出数据集合 + /// 当前可见列数据集合 默认 null 导出全部列 + /// 文件名 默认 null ExportData_{DateTime.Now:yyyyMMddHHmmss}.xlsx + TaskExportPdfAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null); +} diff --git a/src/BootstrapBlazor/Services/ITableExportPdf.cs b/src/BootstrapBlazor/Services/ITableExportPdf.cs new file mode 100644 index 00000000000..5d999fdb302 --- /dev/null +++ b/src/BootstrapBlazor/Services/ITableExportPdf.cs @@ -0,0 +1,23 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Components; + +/// +/// Table 组件 Pdf 导出接口 +/// +public interface ITableExportPdf +{ + ///+ /// 导出 Pdf 数据 + /// + ///+ Task PdfDataAsync(string content); + + /// + /// 导出 Pdf 流 + /// + ///+ Task PdfStreamAsync(string content); +} diff --git a/src/BootstrapBlazor/Services/ITablePdfExport.cs b/src/BootstrapBlazor/Services/ITablePdfExport.cs index 47635f04b7f..342b52c9e59 100644 --- a/src/BootstrapBlazor/Services/ITablePdfExport.cs +++ b/src/BootstrapBlazor/Services/ITablePdfExport.cs @@ -7,6 +7,7 @@ namespace BootstrapBlazor.Components; /// /// Table 组件 Pdf 导出接口 /// +[Obsolete("已过期,统一使用 ITableExport 接口")] public interface ITablePdfExport { ///diff --git a/src/BootstrapBlazor/Utils/CssBuilder.cs b/src/BootstrapBlazor/Utils/CssBuilder.cs index e0f271bb153..19f2d1160ad 100644 --- a/src/BootstrapBlazor/Utils/CssBuilder.cs +++ b/src/BootstrapBlazor/Utils/CssBuilder.cs @@ -16,7 +16,7 @@ public class CssBuilder /// Call Build() to return the completed CSS Classes as a string. /// /// - public static CssBuilder Default(string? value = null) => new CssBuilder(value); + public static CssBuilder Default(string? value = null) => new(value); ////// Creates a CssBuilder used to define conditional CSS classes used in a component. @@ -25,7 +25,7 @@ public class CssBuilder /// protected CssBuilder(string? value) { - stringBuffer = new List ///(); + stringBuffer = []; AddClass(value); } @@ -124,5 +124,5 @@ public CssBuilder AddStyleFromAttributes(IDictionary ? additional /// Finalize the completed CSS Classes as a string. /// string - public string? Build() => stringBuffer.Any() ? string.Join(" ", stringBuffer) : null; + public string? Build() => stringBuffer.Count > 0 ? string.Join(" ", stringBuffer) : null; } diff --git a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/BootstrapBlazor.Html2Pdf.csproj b/src/Extensions/Components/BootstrapBlazor.Html2Pdf/BootstrapBlazor.Html2Pdf.csproj index 4424a56e962..923c1ba81ce 100644 --- a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/BootstrapBlazor.Html2Pdf.csproj +++ b/src/Extensions/Components/BootstrapBlazor.Html2Pdf/BootstrapBlazor.Html2Pdf.csproj @@ -1,7 +1,7 @@- 8.0.1 +8.0.2-beta01 @@ -10,6 +10,7 @@ + diff --git a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs b/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs index e20adabe67d..ee0f9b7c2ee 100644 --- a/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs +++ b/src/Extensions/Components/BootstrapBlazor.Html2Pdf/Services/DefaultPdfService.cs @@ -7,35 +7,39 @@ namespace BootstrapBlazor.Components; ///-/// 构造函数 +/// 默认 Html to Pdf 实现 /// class DefaultPdfService : IHtml2Pdf { ////// - public async Task/// ExportDataAsync(string url, PdfOptions? options = null) + public async Task PdfDataAsync(string url) { using var browserFetcher = new BrowserFetcher(); await browserFetcher.DownloadAsync(); + await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions() { Headless = true }); await using var page = await browser.NewPageAsync(); await page.GoToAsync(url); + var content = await page.GetContentAsync(); - return await page.PdfDataAsync(options ?? new PdfOptions()); + return await page.PdfDataAsync(); } /// /// - public async Task/// ExportStreamAsync(string url, PdfOptions? options = null) + public async Task PdfStreamAsync(string url) { using var browserFetcher = new BrowserFetcher(); await browserFetcher.DownloadAsync(); + await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions() { Headless = true }); await using var page = await browser.NewPageAsync(); await page.GoToAsync(url); + var content = await page.GetContentAsync(); - return await page.PdfStreamAsync(options ?? new PdfOptions()); + return await page.PdfStreamAsync(); } } diff --git a/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/BootstrapBlazor.MaterialDesign.Extensions.csproj b/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/BootstrapBlazor.MaterialDesign.Extensions.csproj index 314f6f30cdb..4b7a451c0d3 100644 --- a/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/BootstrapBlazor.MaterialDesign.Extensions.csproj +++ b/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/BootstrapBlazor.MaterialDesign.Extensions.csproj @@ -1,7 +1,7 @@ diff --git a/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/DefaultIcon.cs b/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/DefaultIcon.cs index 6b701115874..82e590a7272 100644 --- a/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/DefaultIcon.cs +++ b/src/Extensions/Components/BootstrapBlazor.MaterialDesign.Extensions/DefaultIcon.cs @@ -142,8 +142,9 @@ internal class DefaultIcon { ComponentIcons.TableRefreshButtonIcon, "mdi mdi-refresh" }, { ComponentIcons.TableCardViewButtonIcon, "mdi mdi-menu" }, { ComponentIcons.TableColumnListButtonIcon, "mdi mdi-format-list-bulleted" }, - { ComponentIcons.TableExcelExportIcon, "mdi mdi-file-excel" }, - { ComponentIcons.TablePdfExportIcon, "mdi mdi-file-pdf-box" }, + { ComponentIcons.TableExportCsvIcon, "mdi mdi-file-table-box" }, + { ComponentIcons.TableExportExcelIcon, "mdi mdi-file-excel-box" }, + { ComponentIcons.TableExportPdfIcon, "mdi mdi-file-pdf-box" }, { ComponentIcons.TableSearchButtonIcon, "mdi mdi-magnify" }, { ComponentIcons.TableResetSearchButtonIcon, "mdi mdi-trash-can-outline" }, { ComponentIcons.TableCloseButtonIcon, "mdi mdi-close" }, diff --git a/src/Extensions/Components/BootstrapBlazor.TableExport/BootstrapBlazor.TableExport.csproj b/src/Extensions/Components/BootstrapBlazor.TableExport/BootstrapBlazor.TableExport.csproj index 6fcb45b49a1..692f54c9c9b 100644 --- a/src/Extensions/Components/BootstrapBlazor.TableExport/BootstrapBlazor.TableExport.csproj +++ b/src/Extensions/Components/BootstrapBlazor.TableExport/BootstrapBlazor.TableExport.csproj @@ -1,7 +1,7 @@ - 8.0.1 +8.0.2-beta01 @@ -11,7 +11,7 @@ - + - 8.0.0 +8.0.1-beta01 @@ -10,7 +10,7 @@ - diff --git a/src/Extensions/Components/BootstrapBlazor.TableExport/DefaultTableExport.cs b/src/Extensions/Components/BootstrapBlazor.TableExport/DefaultTableExport.cs new file mode 100644 index 00000000000..48d3123dfdc --- /dev/null +++ b/src/Extensions/Components/BootstrapBlazor.TableExport/DefaultTableExport.cs @@ -0,0 +1,172 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using MiniExcelLibs; +using System.Text; + +namespace BootstrapBlazor.Components; + +///+ +/// 构造函数 +/// +/// +class DefaultTableExport(IServiceProvider serviceProvider) : ITableExport +{ + private IServiceProvider ServiceProvider { get; set; } = serviceProvider; + + ///+ /// 导出 方法 + /// + /// 导出数据集合 + /// 导出列集合 默认 null 全部导出 + /// 导出后下载文件名 + ///+ public Task ExportAsync (IEnumerable items, IEnumerable ? cols = null, string? fileName = null) => InternalExportAsync(items, cols, ExcelType.XLSX, fileName); + + /// + /// 导出 Excel 方法 + /// + /// 导出数据集合 + /// 导出列集合 默认 null 全部导出 + /// 导出后下载文件名 + ///+ public Task ExportExcelAsync (IEnumerable items, IEnumerable ? cols = null, string? fileName = null) => InternalExportAsync(items, cols, ExcelType.XLSX, fileName); + + /// + /// + ///+ /// + /// + /// + /// + /// + public Task ExportCsvAsync (IEnumerable items, IEnumerable ? cols, string? fileName = null) => InternalExportAsync(items, cols, ExcelType.CSV, fileName); + + private async Task InternalExportAsync (IEnumerable items, IEnumerable ? cols, ExcelType excelType, string? fileName = null) + { + var value = new List >(); + cols ??= Utility.GetTableColumns (); + foreach (var item in items) + { + if (item != null) + { + var row = new Dictionary (); + foreach (var pi in cols) + { + var val = await FormatValue(pi, Utility.GetPropertyValue(item, pi.GetFieldName())); + row.Add(pi.GetDisplayName(), val); + } + value.Add(row); + } + } + using var stream = new MemoryStream(); + await MiniExcel.SaveAsAsync(stream, value, excelType: excelType); + + fileName ??= $"ExportData_{DateTime.Now:yyyyMMddHHmmss}.{GetExtension()}"; + stream.Position = 0; + var downloadService = ServiceProvider.GetRequiredService (); + await downloadService.DownloadFromStreamAsync(fileName, stream); + return true; + + string GetExtension() => excelType == ExcelType.XLSX ? "xlsx" : "csv"; + } + + private static async Task