mirror of
https://gitee.com/LongbowEnterprise/BootstrapBlazor.git
synced 2024-12-05 13:39:39 +08:00
!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:
parent
ceaba403aa
commit
75feb08357
@ -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",
|
||||
|
@ -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": "自动生成列",
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -53,4 +53,9 @@ public abstract class AutoGenerateBaseAttribute : Attribute
|
||||
/// 获得/设置 字段鼠标悬停提示 默认为 false
|
||||
/// </summary>
|
||||
public bool ShowTips { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否可以拷贝列 默认 false 不可以
|
||||
/// </summary>
|
||||
public bool ShowCopyColumn { get; set; }
|
||||
}
|
||||
|
@ -69,6 +69,11 @@ public interface ITableColumn : IEditorItem
|
||||
/// </summary>
|
||||
BreakPoint ShownWithBreakPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否可以拷贝列 默认 false 不可以
|
||||
/// </summary>
|
||||
bool ShowCopyColumn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 显示模板
|
||||
/// </summary>
|
||||
|
@ -151,6 +151,11 @@ internal class InternalTableColumn : ITableColumn
|
||||
/// </summary>
|
||||
public int GroupOrder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
public bool ShowCopyColumn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)];
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user