六个全新 sgcHTML 反馈组件:Badge、PDFViewer、ContextMenu、ProgressBar、JobProgress 和 LogViewer | eSeGeCe 博客

六个全新 sgcHTML 反馈组件:Badge、PDFViewer、ContextMenu、ProgressBar、JobProgress 和 LogViewer

· 组件

这是介绍 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 代码示例都在各自组件的页面上:BadgePDFViewerContextMenuProgressBarJobProgressLogViewer。本系列的上一篇文章:在线状态、角色与用户管理。

有疑问、反馈,或需要迁移帮助?联系我们 — 回复你的将是编写这些代码的人。