这是介绍 sgcHTML 25 个全新组件的系列文章中的第四篇。这一批组件都在告诉访问者此刻正在发生什么:铃铛图标上的一个计数、内联打开的一份文档、一个右键菜单,以及三种不同的方式来展示进行中的工作 — 一条单独的进度条、一份后台任务列表,以及一段滚动日志。这六个组件都是服务器端渲染的 Delphi/C++Builder/.NET 组件;都不需要你自己接入客户端图表库或 PDF 库。
Badge — 标签、药丸形徽章,或通知圆点
TsgcHTMLComponent_Badge 渲染一个 Bootstrap 5 的 <span class="badge">。设置 Positioned 后,它会变成一个绝对定位的通知圆点,锚定在包裹它的任意 position-relative 元素上,也就是经典的铃铛图标计数效果。
uses
sgcHTML_Enums, sgcHTML_Component_Badge;
var
oBadge: TsgcHTMLComponent_Badge;
begin
oBadge := TsgcHTMLComponent_Badge.Create(nil);
try
oBadge.Text := '3';
oBadge.Color := bgDanger;
oBadge.Pill := True;
oBadge.Positioned := True;
WebModule.Response := oBadge.HTML; // <span class="badge bg-danger rounded-pill ...">
finally
oBadge.Free;
end;
end;
// Or the one-line static helper for a simple inline badge:
WebModule.Response := TsgcHTMLComponent_Badge.Build('New', bgSuccess, True);
PDFViewer — 页面内文档,无需插件
TsgcHTMLComponent_PDFViewer 渲染一个由 pdf.js 驱动的工具栏和画布,内置页面导航、缩放、搜索、下载和打印功能。将 PDFURL 指向一份文档(或用 Base64Data 内嵌字节数据),渲染工作完全在客户端完成。
uses
sgcHTML_Component_PDFViewer;
var
oViewer: TsgcHTMLComponent_PDFViewer;
begin
oViewer := TsgcHTMLComponent_PDFViewer.Create(nil);
try
oViewer.ViewerID := 'invoice';
oViewer.PDFURL := '/invoices/INV-2026-0042.pdf';
oViewer.Height := '700px';
oViewer.InitialPage := 1;
oViewer.Zoom := 'page-width';
oViewer.Theme := pvLight;
oViewer.DownloadFileName := 'invoice-0042.pdf';
WebModule.Response := oViewer.HTML; // toolbar + canvas + pdf.js init script
finally
oViewer.Free;
end;
end;
ContextMenu — 限定于某个选择器范围的右键菜单
TsgcHTMLComponent_ContextMenu 渲染一个在右键点击时打开的 Bootstrap 下拉菜单,仅限于匹配 TargetSelector 的元素。带有 DataAction 的条目会通过你的表单已经在使用的同一通道提交,并触发一个你可以挂钩处理的 DOM 事件。
uses
sgcHTML_Component_ContextMenu;
var
oMenu: TsgcHTMLComponent_ContextMenu;
oItem: TsgcHTMLContextMenuItem;
begin
oMenu := TsgcHTMLComponent_ContextMenu.Create(nil);
try
oMenu.MenuID := 'grid_menu';
oMenu.TargetSelector := '.grid-row';
oItem := oMenu.Items.Add;
oItem.Caption := 'Edit';
oItem.Icon := 'bi bi-pencil';
oItem.DataAction := 'row:edit';
oItem := oMenu.Items.Add;
oItem.Caption := 'Delete';
oItem.Icon := 'bi bi-trash';
oItem.DataAction := 'row:delete';
oItem := oMenu.Items.Add;
oItem.Divider := True;
oItem := oMenu.Items.Add;
oItem.Caption := 'Open in new tab';
oItem.Href := '/grid/open';
WebModule.Response := oMenu.HTML; // hidden <ul> + right-click binding script
finally
oMenu.Free;
end;
end;
ProgressBar — 单条进度条或堆叠分段
TsgcHTMLComponent_ProgressBar 同时覆盖简单场景 — 单个 Value/Max,带条纹和动画效果 — 以及堆叠场景:向 Bars 添加条目后,它们会把单条进度条替换成多段式进度条,每一段都有自己的颜色和标签。
uses
sgcHTML_Enums, sgcHTML_Component_ProgressBar;
var
oBar: TsgcHTMLComponent_ProgressBar;
begin
oBar := TsgcHTMLComponent_ProgressBar.Create(nil);
try
oBar.ProgressBarID := 'upload';
oBar.Value := 72;
oBar.Max := 100;
oBar.ColorStyle := hcSuccess;
oBar.Striped := True;
oBar.Animated := True;
oBar.ShowLabel := True;
oBar.LabelFormat := '%d%% complete';
WebModule.Response := oBar.HTML; // Bootstrap progress bar
finally
oBar.Free;
end;
end;
// Or a stacked, multi-segment bar:
with oBar.Bars.Add do
begin
Value := 40;
ColorStyle := hcPrimary;
Label_ := 'Done';
end;
with oBar.Bars.Add do
begin
Value := 20;
ColorStyle := hcWarning;
Label_ := 'In progress';
end;
JobProgress — 实时的后台任务列表
当你需要同时跟踪不止一件事时,TsgcHTMLComponent_JobProgress 就是 ProgressBar 进化后的样子:一张卡片列出每一个后台任务,各自带有自己的状态徽章和进度条。AddJob 用于注册一个任务,UpdateJob 用于推进它的进度,而 GetJobFragmentHTML 只把这一行推送给已连接的客户端,而不必重新渲染整个列表。
uses
sgcHTML_Enums, sgcHTML_Component_JobProgress;
var
oJobs: TsgcHTMLComponent_JobProgress;
begin
oJobs := TsgcHTMLComponent_JobProgress.Create(nil);
try
oJobs.JobsID := 'exports';
oJobs.Title := 'Background Exports';
oJobs.ShowCompleted := False;
oJobs.AddJob('exp-42', 'Export customers.csv', 'Generating CSV export');
WebModule.Response := oJobs.HTML; // card + progress rows + cancel-form script
finally
oJobs.Free;
end;
end;
// On a later progress tick, push just that row over the WebSocket:
oJobs.UpdateJob('exp-42', 65, jsRunning);
Engine.BroadcastFragment(oJobs.GetJobFragmentHTML('exp-42'));
LogViewer — 流式终端,内置级别过滤
TsgcHTMLComponent_LogViewer 渲染一个深色或浅色的终端风格面板,带有搜索框和级别过滤器,由一个设有上限的环形缓冲区(MaxLines)支撑,因此它不会无限增长。AddLine 追加一条带时间戳、按颜色编码的日志;GetLastLineFragmentHTML 会把新的日志行流式推送给每一个已打开的客户端,而无需完整重新渲染。
uses
sgcHTML_Component_LogViewer;
var
oLog: TsgcHTMLComponent_LogViewer;
begin
oLog := TsgcHTMLComponent_LogViewer.Create(nil);
try
oLog.LogID := 'applog';
oLog.Theme := ltDark;
oLog.MaxLines := 500;
oLog.Height := '400px';
oLog.AddLine(llInfo, 'Service started', 'app');
oLog.AddLine(llWarning, 'Low disk space', 'monitor');
oLog.AddLine(llError, 'Connection refused', 'db');
WebModule.Response := oLog.HTML; // toolbar + log body + inline script
finally
oLog.Free;
end;
end;
// Push one more line to every connected client, no full re-render:
oLog.AddLine(llInfo, 'New order received', 'orders');
TsgcHTMX_Engine_Server.BroadcastFragment(oLog.GetLastLineFragmentHTML);
立即体验
完整文档、关键属性参考以及 Delphi/C++Builder/.NET 代码示例都在各自组件的页面上:Badge、PDFViewer、ContextMenu、ProgressBar、JobProgress 和 LogViewer。本系列的上一篇文章:在线状态、角色与用户管理。
有疑问、反馈,或需要迁移帮助?联系我们 — 回复你的将是编写这些代码的人。
