zhaolei
2020-11-20 921de2254ff5712a44ed8575ee8efe34252f6603
commit | author | age
921de2 1 using Bootstrap.Admin.Pages.Extensions;
Z 2 using Bootstrap.Admin.Pages.Shared;
3 using Microsoft.AspNetCore.Components;
4 using Microsoft.AspNetCore.Components.Forms;
5 using Microsoft.JSInterop;
6 using System;
7 using System.Collections.Generic;
8 using System.Linq;
9
10 namespace Bootstrap.Admin.Pages.Components
11 {
12     /// <summary>
13     /// 表格组件类
14     /// </summary>
15     public class TableBase<TItem> : ComponentBase
16     {
17         /// <summary>
18         /// 获得 IJSRuntime 实例
19         /// </summary>
20         [Inject]
21         protected IJSRuntime? JSRuntime { get; set; }
22
23         /// <summary>
24         /// 每页数据数量 默认 20 行
25         /// </summary>
26         protected const int DefaultPageItems = 20;
27
28         /// <summary>
29         /// 获得/设置 组件 Id
30         /// </summary>
31         [Parameter]
32         public string Id { get; set; } = "";
33
34         /// <summary>
35         /// 获得/设置 TableHeader 实例
36         /// </summary>
37         [Parameter]
38         public RenderFragment<TItem>? TableHeader { get; set; }
39
40         /// <summary>
41         /// 获得/设置 RowTemplate 实例
42         /// </summary>
43         [Parameter]
44         public RenderFragment<TItem>? RowTemplate { get; set; }
45
46         /// <summary>
47         /// 获得/设置 按钮模板 实例
48         /// </summary>
49         [Parameter]
50         public RenderFragment<TItem>? ButtonTemplate { get; set; }
51
52         /// <summary>
53         /// 获得/设置 EditTemplate 实例
54         /// </summary>
55         [Parameter]
56         public RenderFragment<TItem>? EditTemplate { get; set; }
57
58         /// <summary>
59         /// 获得/设置 SearchTemplate 实例
60         /// </summary>
61         [Parameter]
62         public RenderFragment<TItem>? SearchTemplate { get; set; }
63
64         /// <summary>
65         /// 获得/设置 表格 Toolbar 按钮模板
66         /// </summary>
67         [Parameter]
68         public RenderFragment? TableToolbarTemplate { get; set; }
69
70         /// <summary>
71         /// 获得/设置 TableFooter 实例
72         /// </summary>
73         [Parameter]
74         public RenderFragment? TableFooter { get; set; }
75
76         /// <summary>
77         /// 获得/设置 是否固定表头 默认为 false 不固定表头
78         /// </summary>
79         [Parameter]
80         public bool FixedHeader { get; set; }
81
82         /// <summary>
83         /// 获得/设置 是否自适应高度 默认为 false 不自适应高度
84         /// </summary>
85         [Parameter]
86         public bool AutoHeight { get; set; }
87
88         /// <summary>
89         /// 获得/设置 是否显示搜索框 默认为 false 不显示搜索框
90         /// </summary>
91         [Parameter]
92         public bool ShowSearch { get; set; }
93
94         /// <summary>
95         /// 获得/设置 是否显示高级搜索按钮 默认显示
96         /// </summary>
97         [Parameter]
98         public bool ShowAdvancedSearch { get; set; } = true;
99
100         /// <summary>
101         /// 获得/设置 数据集合
102         /// </summary>
103         protected IEnumerable<TItem> Items { get; set; } = new TItem[0];
104
105         /// <summary>
106         /// 获得/设置 已选择的数据集合
107         /// </summary>
108         public List<TItem> SelectedItems { get; } = new List<TItem>();
109
110         /// <summary>
111         /// 获得/设置 是否显示行号
112         /// </summary>
113         [Parameter]
114         public bool ShowLineNo { get; set; } = true;
115
116         /// <summary>
117         /// 获得/设置 是否显示选择列 默认为 false
118         /// </summary>
119         [Parameter]
120         public bool ShowCheckbox { get; set; }
121
122         /// <summary>
123         /// 获得/设置 是否显示按钮列 默认为 false
124         /// </summary>
125         [Parameter]
126         public bool ShowDefaultButtons { get; set; }
127
128         /// <summary>
129         /// 获得/设置 是否显示表脚 默认为 false
130         /// </summary>
131         [Parameter]
132         public bool ShowFooter { get; set; }
133
134         /// <summary>
135         /// 获得/设置 是否显示扩展按钮 默认为 true
136         /// </summary>
137         [Parameter]
138         public bool ShowExtendButtons { get; set; }
139
140         /// <summary>
141         /// 获得/设置 是否显示刷新按钮 默认为 true
142         /// </summary>
143         [Parameter]
144         public bool ShowRefresh { get; set; }
145
146         /// <summary>
147         /// 获得/设置 是否分页组件 默认为 false
148         /// </summary>
149         [Parameter]
150         public bool ShowPagination { get; set; } = true;
151
152         /// <summary>
153         /// 获得/设置 是否显示工具栏 默认为 true
154         /// </summary>
155         [Parameter]
156         public bool ShowToolBar { get; set; }
157
158         /// <summary>
159         /// 获得/设置 按钮列 Header 文本 默认为 操作
160         /// </summary>
161         [Parameter]
162         public string ButtonTemplateHeaderText { get; set; } = "操作";
163
164         /// <summary>
165         /// 点击翻页回调方法
166         /// </summary>
167         [Parameter]
168         public Func<QueryPageOptions, QueryData<TItem>>? OnQuery { get; set; }
169
170         /// <summary>
171         /// 新建按钮回调方法
172         /// </summary>
173         [Parameter]
174         public Func<TItem>? OnAdd { get; set; }
175
176         /// <summary>
177         /// 编辑按钮回调方法
178         /// </summary>
179         [Parameter]
180         public Action<TItem>? OnEdit { get; set; }
181
182         /// <summary>
183         /// 保存按钮回调方法
184         /// </summary>
185         [Parameter]
186         public Func<TItem, bool>? OnSave { get; set; }
187
188         /// <summary>
189         /// 表头排序时回调方法
190         /// </summary>
191         [Parameter]
192         public Action<string, SortOrder> OnSort { get; set; } = new Action<string, SortOrder>((name, order) => { });
193
194         /// <summary>
195         /// 删除按钮回调方法
196         /// </summary>
197         [Parameter]
198         public Func<IEnumerable<TItem>, bool>? OnDelete { get; set; }
199
200         /// <summary>
201         /// 获得/设置 每页数据数量
202         /// </summary>
203         [Parameter]
204         public int PageItems { get; set; } = DefaultPageItems;
205
206 #nullable disable
207         /// <summary>
208         /// 获得/设置 EditModel 实例
209         /// </summary>
210         [Parameter]
211         public TItem EditModel { get; set; }
212
213         /// <summary>
214         /// 获得/设置 QueryModel 实例
215         /// </summary>
216         [Parameter]
217         public TItem QueryModel { get; set; }
218 #nullable restore
219
220         /// <summary>
221         /// 编辑数据弹窗 Title
222         /// </summary>
223         [Parameter]
224         public string SubmitModalTitle { get; set; } = "";
225
226         /// <summary>
227         /// 编辑数据弹窗
228         /// </summary>
229         protected SubmitModal<TItem>? EditModal { get; set; }
230
231         /// <summary>
232         /// 确认删除弹窗
233         /// </summary>
234         protected Modal? ConfirmModal { get; set; }
235
236         /// <summary>
237         /// 高级查询弹窗
238         /// </summary>
239         protected Modal? SearchModal { get; set; }
240
241         /// <summary>
242         /// 获得/设置 数据总条目
243         /// </summary>
244         protected int TotalCount { get; set; }
245
246         /// <summary>
247         /// 获得/设置 当前页码
248         /// </summary>
249         protected int PageIndex { get; set; } = 1;
250
251         /// <summary>
252         /// 获得/设置 当前排序字段名称
253         /// </summary>
254         protected string SortName { get; set; } = "";
255
256         /// <summary>
257         /// 获得/设置 当前排序规则
258         /// </summary>
259         protected SortOrder SortOrder { get; set; }
260
261         /// <summary>
262         /// OnInitialized 方法
263         /// </summary>
264         protected override void OnInitialized()
265         {
266             OnSort = new Action<string, SortOrder>((sortName, sortOrder) =>
267             {
268                 (SortName, SortOrder) = (sortName, sortOrder);
269                 Query();
270             });
271             if (EditModel == null && OnAdd != null) EditModel = OnAdd.Invoke();
272             if (OnQuery != null)
273             {
274                 var queryData = OnQuery(new QueryPageOptions() { PageItems = DefaultPageItems, SearchText = SearchText, SortName = SortName, SortOrder = SortOrder });
275                 Items = queryData.Items;
276                 TotalCount = queryData.TotalCount;
277             }
278         }
279
280         /// <summary>
281         /// OnAfterRenderAsync 方法
282         /// </summary>
283         protected override async System.Threading.Tasks.Task OnAfterRenderAsync(bool firstRender)
284         {
285             // 调用客户端脚本
286             await JSRuntime.InitTableAsync(RetrieveId(), firstRender);
287         }
288
289         /// <summary>
290         /// 点击页码调用此方法
291         /// </summary>
292         /// <param name="pageIndex"></param>
293         /// <param name="pageItems"></param>
294         protected void PageClick(int pageIndex, int pageItems)
295         {
296             if (pageIndex != PageIndex)
297             {
298                 PageIndex = pageIndex;
299                 PageItems = pageItems;
300                 Query();
301             }
302         }
303
304         /// <summary>
305         /// 每页记录条数变化是调用此方法
306         /// </summary>
307         protected void PageItemsChange(int pageItems)
308         {
309             if (OnQuery != null)
310             {
311                 PageIndex = 1;
312                 PageItems = pageItems;
313                 Query();
314             }
315         }
316
317         /// <summary>
318         /// 选择框点击时调用此方法
319         /// </summary>
320         /// <param name="item"></param>
321         /// <param name="check"></param>
322         protected void ToggleCheck(TItem item, bool check)
323         {
324             if (item == null)
325             {
326                 SelectedItems.Clear();
327                 if (check) SelectedItems.AddRange(Items);
328             }
329             else
330             {
331                 if (check) SelectedItems.Add(item);
332                 else SelectedItems.Remove(item);
333             }
334             StateHasChanged();
335         }
336
337         /// <summary>
338         /// 表头 CheckBox 状态更新方法
339         /// </summary>
340         /// <returns></returns>
341         protected CheckBoxState CheckState(TItem item)
342         {
343             var ret = CheckBoxState.UnChecked;
344             if (SelectedItems.Count > 0)
345             {
346                 ret = SelectedItems.Count == Items.Count() ? CheckBoxState.Checked : CheckBoxState.Mixed;
347             }
348             return ret;
349         }
350
351         /// <summary>
352         /// 新建按钮方法
353         /// </summary>
354         public void Add()
355         {
356             if (OnAdd != null) EditModel = OnAdd.Invoke();
357             SelectedItems.Clear();
358             EditModal?.Toggle();
359         }
360
361         /// <summary>
362         /// 显示提示信息
363         /// </summary>
364         /// <param name="title"></param>
365         /// <param name="text"></param>
366         /// <param name="cate"></param>
367         protected void ShowMessage(string title, string text, ToastCategory cate = ToastCategory.Success) => JSRuntime?.ShowToast(title, text, cate);
368
369         /// <summary>
370         /// 编辑按钮方法
371         /// </summary>
372         public void Edit()
373         {
374             if (SelectedItems.Count == 1)
375             {
376 #nullable disable
377                 EditModel = SelectedItems[0].Clone();
378 #nullable restore
379                 EditModal?.Toggle();
380             }
381             else
382             {
383                 ShowMessage("编辑数据", "请选择一个要编辑的数据", ToastCategory.Information);
384             }
385         }
386
387         /// <summary>
388         /// 查询按钮调用此方法
389         /// </summary>
390         public void Query()
391         {
392             if (OnQuery != null)
393             {
394                 SelectedItems.Clear();
395                 var queryData = OnQuery(new QueryPageOptions()
396                 {
397                     PageIndex = PageIndex,
398                     PageItems = PageItems,
399                     SearchText = SearchText,
400                     SortOrder = SortOrder,
401                     SortName = SortName
402                 });
403                 Items = queryData.Items;
404                 PageIndex = queryData.PageIndex;
405                 TotalCount = queryData.TotalCount;
406                 StateHasChanged();
407             }
408         }
409
410         /// <summary>
411         /// 保存数据
412         /// </summary>
413         /// <param name="context"></param>
414         protected void Save(EditContext context)
415         {
416             var valid = OnSave?.Invoke((TItem)context.Model) ?? false;
417             if (valid)
418             {
419                 EditModal?.Toggle();
420                 Query();
421             }
422             ShowMessage("保存数据", "保存数据" + (valid ? "成功" : "失败"), valid ? ToastCategory.Success : ToastCategory.Error);
423         }
424
425         /// <summary>
426         /// 删除按钮方法
427         /// </summary>
428         public void Delete()
429         {
430             if (SelectedItems.Count > 0)
431             {
432                 ConfirmModal?.Toggle();
433             }
434             else
435             {
436                 ShowMessage("删除数据", "请选择要删除的数据", ToastCategory.Information);
437             }
438         }
439
440         /// <summary>
441         /// 确认删除方法
442         /// </summary>
443         public void Confirm()
444         {
445             var result = OnDelete?.Invoke(SelectedItems) ?? false;
446             if (result)
447             {
448                 ConfirmModal?.Toggle();
449                 Query();
450             }
451             ShowMessage("删除数据", "删除数据" + (result ? "成功" : "失败"), result ? ToastCategory.Success : ToastCategory.Error);
452         }
453
454         /// <summary>
455         /// 获取 Id 字符串
456         /// </summary>
457         protected string RetrieveId() => $"{Id}_table";
458
459         /// <summary>
460         /// 重置搜索按钮回调方法
461         /// </summary>
462         [Parameter]
463         public Action? OnResetSearch { get; set; }
464
465         /// <summary>
466         /// 重置查询方法
467         /// </summary>
468         protected void ResetSearchClick()
469         {
470             OnResetSearch?.Invoke();
471             SearchClick();
472         }
473
474         /// <summary>
475         /// 查询方法
476         /// </summary>
477         protected void SearchClick()
478         {
479             // 查询控件按钮触发此事件
480             PageIndex = 1;
481             Query();
482         }
483
484         /// <summary>
485         /// 高级查询按钮点击时调用此方法
486         /// </summary>
487         protected void AdvancedSearchClick()
488         {
489             // 弹出高级查询弹窗
490             SearchModal?.Toggle();
491         }
492
493         /// <summary>
494         /// 获得/设置 搜索关键字
495         /// </summary>
496         [Parameter]
497         public string SearchText { get; set; } = "";
498
499         /// <summary>
500         /// 获得/设置 搜索关键字改变事件
501         /// </summary>
502         [Parameter]
503         public EventCallback<string> SearchTextChanged { get; set; }
504
505         /// <summary>
506         /// 重置搜索按钮调用此方法
507         /// </summary>
508         protected void ClearSearchClick()
509         {
510             SearchText = "";
511             Query();
512         }
513     }
514 }