!3548 feat(#I623F1): add ShowCopyColumn parameter on TableColumn

* refactor: 移除重复属性
* chore: 更新打包文件
* Merge branch 'main' into feat/table
* chore: 增加资源文件与拷贝列示例
* refactor: 恢复默认值
* chore: 更新示例文档
* feat: 支持固定列虚拟滚动拷贝列数据
* feat: 增加 Excel 表格拷贝支持
* chore: 更新动态列示例
* feat: 动态表格增加拷贝列功能
* feat: 列拷贝兼容明细行表格
* feat: 列拷贝图标更改到文字前面
* feat: 增加列拷贝 Tooltip 相关功能实现代码
* feat: 增加 ShowCopyColumn 参数
* feat: 增加列拷贝脚本
* feat: 增加列拷贝功能
This commit is contained in:
Argo 2022-11-20 13:39:00 +00:00
parent ceaba403aa
commit 75feb08357
19 changed files with 195 additions and 14 deletions

View File

@ -4656,7 +4656,10 @@
"VisibleP4": "Trigger the <code>OnColumnVisibleChanged</code> callback when switch the column state <b>Show/Hide</b>",
"AllowResizingTitle": "Allow column resizing",
"AllowResizingIntro": "Set table columns to allow resizing by specifying <code>AllowResizing</code>",
"AllowResizingP1": "Column resizing can only be done when the screen is too small and the scroll bar appears",
"AllowResizingDesc": "Column resizing can only be done when the screen is too small and the scroll bar appears",
"ShowCopyColumnTitle": "Show copy column icon",
"ShowCopyColumnIntro": "Set <code>ShowCopyColumn</code> show the icon for copy entire column data",
"ShowCopyColumnDesc": "可以通过设置 <code>ShowCopyColumnTooltip</code> <code>CopyColumnTooltipText</code> <code>CopyColumnCopiedTooltipText</code> 等设置微调拷贝列数据图标的 <code>Tooltip</code> 相关参数",
"TemplateTitle": "Custom Column Template",
"TemplateIntro": "By specifying <code>Template</code> set the last column to display as a custom button",
"AutoGenerateColumnsTitle": "Auto Generate Columns",

View File

@ -4675,7 +4675,10 @@
"VisibleP4": "更改 <b>列</b> 状态后触发 <code>OnColumnVisibleChanged</code> 回调委托",
"AllowResizingTitle": "允许列调整",
"AllowResizingIntro": "通过指定 <code>AllowResizing</code> 设置表格列允许调整宽度",
"AllowResizingP1": "屏幕过小出现滚动条时才可以进行列调整",
"AllowResizingDesc": "屏幕过小出现滚动条时才可以进行列调整",
"ShowCopyColumnTitle": "允许拷贝列数据",
"ShowCopyColumnIntro": "通过设置 <code>ShowCopyColumn</code> 设置表格列允许拷贝整列数据",
"ShowCopyColumnDesc": "可以通过设置 <code>ShowCopyColumnTooltip</code> <code>CopyColumnTooltipText</code> <code>CopyColumnCopiedTooltipText</code> 等设置微调拷贝列数据图标的 <code>Tooltip</code> 相关参数",
"TemplateTitle": "自定义列模板",
"TemplateIntro": "通过指定 <code>Template</code> 设置最后一列内显示为自定义按钮",
"AutoGenerateColumnsTitle": "自动生成列",

View File

@ -206,7 +206,7 @@
</DemoBlock>
<DemoBlock Title="@ColumnLocalizer["AllowResizingTitle"]" Introduction="@ColumnLocalizer["AllowResizingIntro"]" Name="AllowResizing">
<p>@((MarkupString)ColumnLocalizer["AllowResizingP1"].Value)</p>
<p>@((MarkupString)ColumnLocalizer["AllowResizingDesc"].Value)</p>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource" AllowResizing="true"
IsStriped="true" IsBordered="true"
@ -221,6 +221,24 @@
</Table>
</DemoBlock>
<DemoBlock Title="@ColumnLocalizer["ShowCopyColumnTitle"]" Introduction="@ColumnLocalizer["ShowCopyColumnIntro"]" Name="ShowCopyColumn">
<p>@((MarkupString)ColumnLocalizer["ShowCopyColumnDesc"].Value)</p>
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource" AllowResizing="true"
IsStriped="true" IsBordered="true"
ShowToolbar="false" IsMultipleSelect="true" ShowExtendButtons="false"
OnQueryAsync="@OnQueryAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="120" FormatString="yyyy-MM-dd" ShowCopyColumn="true" />
<TableColumn @bind-Field="@context.Name" Width="100" ShowCopyColumn="true" />
<TableColumn @bind-Field="@context.Address" ShowCopyColumn="true" />
<TableColumn @bind-Field="@context.Count" ShowCopyColumn="true" />
<TableColumn @bind-Field="@context.Education" ShowCopyColumn="true" />
<TableColumn @bind-Field="@context.Complete" ShowCopyColumn="true" />
</TableColumns>
</Table>
</DemoBlock>
<DemoBlock Title="@ColumnLocalizer["TemplateTitle"]" Introduction="@ColumnLocalizer["TemplateIntro"]" Name="Template">
<Table TItem="Foo"
IsPagination="true" PageItemsSource="@PageItemsSource"

View File

@ -2,7 +2,7 @@
@inject IStringLocalizer<TablesDynamicObject> Localizer
<h3>@Localizer["H1"]</h3>
<h4>@Localizer["H2"]</h4>
<h4>@((MarkupString)Localizer["H2"].Value)</h4>
<DemoBlock Title="@Localizer["P1"]" Introduction="@Localizer["P2"]" Name="IDynamicMetaObjectProvider">
<Table TItem="CustomDynamicData" OnQueryAsync="OnQueryAsync"

View File

@ -1,17 +1,18 @@
@page "/tables/export"
<h3>@Localizer["H1"]</h3>
<h4>@Localizer["H2"]</h4>
<h4>@((MarkupString)Localizer["H2"].Value)</h4>
<p>@Localizer["P1"]</p>
<p>@((MarkupString)@Localizer["P1"].Value)</p>
<p><b>@Localizer["P2"]</b></p>
<p><a href="https://www.nuget.org/packages?q=BootstrapBlazor.TableExport" target="_blank">@Localizer["P3"]</a></p>
<Tips>
<div class="mb-2"><b>@Localizer["P2"]</b></div>
<p><a href="https://www.nuget.org/packages?q=BootstrapBlazor.TableExport" target="_blank">@((MarkupString)@Localizer["P3"].Value)</a></p>
</Tips>
<p><b>@Localizer["P4"]</b></p>
<p>@((MarkupString)Localizer["P5"].Value) <a href="https://www.nuget.org/packages?q=BootstrapBlazor.TableExport" target="_blank">nuget.org</a> @Localizer["P6"]</p>
<p>@((MarkupString)Localizer["P5"].Value) <a href="https://www.nuget.org/packages?q=BootstrapBlazor.TableExport" target="_blank">nuget.org</a> @((MarkupString)@Localizer["P6"].Value)</p>
<div class="code-label">.NET CLI</div>
<Pre class="no-highlight">dotnet add package BootstrapBlazor.TableExport --version @Version</Pre>

View File

@ -1,7 +1,7 @@
@page "/tables/selection"
<h3>@Localizer["H1"]</h3>
<h4>@Localizer["H2"]</h4>
<h4>@((MarkupString)Localizer["H2"].Value)</h4>
<DemoBlock Title="@Localizer["P1"]" Introduction="@Localizer["P2"]" Name="SelectedRow">
<Table TItem="Foo" @bind-SelectedRows="SelectedItems"

View File

@ -53,4 +53,9 @@ public abstract class AutoGenerateBaseAttribute : Attribute
/// 获得/设置 字段鼠标悬停提示 默认为 false
/// </summary>
public bool ShowTips { get; set; }
/// <summary>
/// 获得/设置 是否可以拷贝列 默认 false 不可以
/// </summary>
public bool ShowCopyColumn { get; set; }
}

View File

@ -69,6 +69,11 @@ public interface ITableColumn : IEditorItem
/// </summary>
BreakPoint ShownWithBreakPoint { get; set; }
/// <summary>
/// 获得/设置 是否可以拷贝列 默认 false 不可以
/// </summary>
bool ShowCopyColumn { get; set; }
/// <summary>
/// 获得/设置 显示模板
/// </summary>

View File

@ -151,6 +151,11 @@ internal class InternalTableColumn : ITableColumn
/// </summary>
public int GroupOrder { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
public bool ShowCopyColumn { get; set; }
/// <summary>
/// 构造函数
/// </summary>

View File

@ -16,6 +16,7 @@
--bs-table-striped-bg: rgba(0,0,0,.05);
--bs-table-hover-bg: rgba(0,0,0,.075);
--bb-table-search-body-margin: 1rem;
--bb-table-copy-column-margin-right: .5rem;
--bb-loader-bg: #f8f9fa;
}
@ -779,3 +780,8 @@ form .table .table-cell > textarea {
.table-page-info .select {
width: 120px;
}
.col-copy {
cursor: pointer;
margin-right: var(--bb-table-copy-column-margin-right);
}

View File

@ -469,6 +469,19 @@ RenderFragment<bool> RenderHeader => hasScroll =>
<DynamicElement TagName="th" class="@GetHeaderClassString(col)" style="@GetFixedCellStyleString(col, 6)"
TriggerClick="col.Sortable" OnClick="@OnClickHeader(col)">
<div class="@GetHeaderWrapperClassString(col)">
@if(col.ShowCopyColumn)
{
if (ShowCopyColumnTooltip)
{
<Tooltip Placement="Placement.Top" Trigger="hover" Title="@CopyColumnTooltipText" data-bb-title="@CopyColumnCopiedTooltipText">
<i class="fa-regular fa-clipboard col-copy"></i>
</Tooltip>
}
else
{
<i class="fa-regular fa-clipboard col-copy"></i>
}
}
@if(col.HeaderTemplate != null)
{
@col.HeaderTemplate(col)

View File

@ -329,5 +329,7 @@ public partial class Table<TItem>
ExportToastContent ??= Localizer[nameof(ExportToastContent)];
ExportToastInProgressContent ??= Localizer[nameof(ExportToastInProgressContent)];
ExportExcelDropdownItemText ??= Localizer[nameof(ExportExcelDropdownItemText)];
CopyColumnTooltipText ??= Localizer[nameof(CopyColumnTooltipText)];
CopyColumnCopiedTooltipText ??= Localizer[nameof(CopyColumnCopiedTooltipText)];
}
}

View File

@ -123,6 +123,24 @@ public partial class Table<TItem> : ITable where TItem : class, new()
private static string? GetColspan(int colspan) => colspan > 1 ? colspan.ToString() : null;
/// <summary>
/// 获得/设置 列拷贝 Tooltip 文字
/// </summary>
[Parameter]
public string? CopyColumnTooltipText { get; set; }
/// <summary>
/// 获得/设置 列拷贝完毕后 Tooltip 文字
/// </summary>
[Parameter]
public string? CopyColumnCopiedTooltipText { get; set; }
/// <summary>
/// 获得/设置 CopyColumn Tooltip 默认 true
/// </summary>
[Parameter]
public bool ShowCopyColumnTooltip { get; set; } = true;
/// <summary>
/// 明细行集合用于数据懒加载
/// </summary>

View File

@ -172,6 +172,12 @@ public class TableColumn<TItem, TType> : BootstrapComponentBase, ITableColumn
[Parameter]
public bool Fixed { get; set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
[Parameter]
public bool ShowCopyColumn { get; set; }
/// <summary>
/// 获得/设置 是否显示本列 默认 true 显示
/// </summary>

View File

@ -23,6 +23,7 @@ public static class IEditItemExtensions
if (source.Readonly) dest.Readonly = source.Readonly;
if (source.Searchable) dest.Searchable = source.Searchable;
if (source.ShowTips) dest.ShowTips = source.ShowTips;
if (source.ShowCopyColumn) dest.ShowCopyColumn = source.ShowCopyColumn;
if (source.Sortable) dest.Sortable = source.Sortable;
if (source.TextEllipsis) dest.TextEllipsis = source.TextEllipsis;
}
@ -77,6 +78,7 @@ public static class IEditItemExtensions
if (col.TextEllipsis) dest.TextEllipsis = col.TextEllipsis;
if (!col.Visible) dest.Visible = col.Visible;
if (col.Width != null) dest.Width = col.Width;
if (col.ShowCopyColumn) dest.ShowCopyColumn = col.ShowCopyColumn;
}
}

View File

@ -232,7 +232,9 @@
"ExportToastInProgressContent": "Exporting data, please waiting a moment, auto close after {0}s",
"ExportExcelDropdownItemText": "MS-Excel",
"PageInfoText": "{0} - {1} Total {2}",
"PageItemsText": "{0}/page"
"PageItemsText": "{0}/page",
"CopyColumnTooltipText": "Copy entire column data to clipboard",
"CopyColumnCopiedTooltipText": "Copied!"
},
"BootstrapBlazor.Components.EditDialog": {
"CloseButtonText": "Close",

View File

@ -232,7 +232,9 @@
"ExportToastInProgressContent": "正在导出数据,请稍后, {0} 秒后自动关闭",
"ExportExcelDropdownItemText": "微软 Excel 格式",
"PageInfoText": "{0} - {1} 共 {2} 条",
"PageItemsText": "{0} 条/页"
"PageItemsText": "{0} 条/页",
"CopyColumnTooltipText": "拷贝列内容到剪切板",
"CopyColumnCopiedTooltipText": "已拷贝"
},
"BootstrapBlazor.Components.EditDialog": {
"CloseButtonText": "关闭",

File diff suppressed because one or more lines are too long

View File

@ -35,6 +35,10 @@ export class Table extends BlazorComponent {
if (this._isResizeColumn) {
this._setResizeListener()
}
if (true) {
this._setCopyColumn()
}
}
_execute(args) {
@ -279,6 +283,90 @@ export class Table extends BlazorComponent {
})
}
_setCopyColumn() {
const copyCellValue = td => {
let ret = null;
let input = td.querySelector('.datetime-picker-input')
if (input === null) {
input = td.querySelector('.form-select')
}
if (input === null) {
input = td.querySelector('.switch')
if (input) {
if (input.classList.contains('is-checked')) {
ret = 'True'
}
else {
ret = 'False'
}
return ret
}
}
if (input) {
ret = input.value
}
else {
ret = td.textContent
}
return ret
}
EventHandler.on(this._element, 'click', '.col-copy', e => {
const index = e.delegateTarget.closest('th').cellIndex
let rows
if (this._fixedHeader) {
rows = this._body.querySelectorAll('table > tbody > tr')
}
else if (this._element.querySelector('.table-fixed-column')) {
rows = this._element.querySelectorAll('.table-scroll > .overflow-auto > table > tbody > tr')
}
else {
rows = this._element.querySelectorAll('.table-scroll > table > tbody > tr')
}
let content = ''
rows.forEach(row => {
if (!row.classList.contains('is-detail')) {
const td = row.childNodes[index]
const v = copyCellValue(td)
if (v !== null) {
content += `${v}\n`
}
}
})
this._copy(content)
const span = e.delegateTarget.parentNode
const tooltip = getDescribedElement(span)
const tip = bootstrap.Tooltip.getInstance(span)
if (tooltip) {
tooltip.querySelector('.tooltip-inner').innerHTML = span.getAttribute('data-bb-title')
tip.update()
}
const handler = window.setTimeout(() => {
window.clearTimeout(handler)
if (tooltip) {
tooltip.querySelector('.tooltip-inner').innerHTML = span.getAttribute('data-bs-original-title')
tip.update()
}
}, 1000);
})
}
_copy = (text = '') => {
if (navigator.clipboard) {
navigator.clipboard.writeText(text)
} else {
const input = document.createElement('textarea')
input.setAttribute('value', text)
input.setAttribute('hidden', 'true')
document.body.appendChild(input)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
}
}
_dispose() {
if (this._fixedHeader) {
EventHandler.off(this._body, 'scroll')
@ -292,6 +380,8 @@ export class Table extends BlazorComponent {
EventHandler.off(col, 'mousedown')
EventHandler.off(col, 'touchstart')
})
EventHandler.off(this._element, 'click', '.col-copy')
}
static getResponsive() {