本页给出一个流程状态面板示例,把 Steps 与 Timeline 组合起来:上方步骤条表示当前阶段,下方时间轴记录处理日志,右侧按钮驱动流程推进、回退、异常与完成。
重点:
Steps.Current使用 .NET/AntdUI 习惯从0开始计数;而 aardio 数组从1开始,所以用业务数组取标题时通常写为stageTitles[current + 1]。
import win.ui;
import dotNet.AntdUI;
import System;
/*DSG{{*/
var winform = win.form(text="Steps + Timeline 工单流转面板";right=980;bottom=620)
winform.add(
btnDoneHost={cls="custom";text="完成";left=830;top=510;right=930;bottom=548;db=1;dr=1;frame=1;z=10};
btnErrorHost={cls="custom";text="标记异常";left=700;top=510;right=800;bottom=548;db=1;dr=1;frame=1;z=9};
btnNextHost={cls="custom";text="下一步";left=830;top=456;right=930;bottom=494;db=1;dr=1;frame=1;z=8};
btnPrevHost={cls="custom";text="上一步";left=700;top=456;right=800;bottom=494;db=1;dr=1;frame=1;z=7};
divFlowHost={cls="custom";text="当前流程";left=24;top=18;right=940;bottom=48;dl=1;dr=1;dt=1;z=1};
divLogHost={cls="custom";text="处理时间轴";left=24;top=136;right=620;bottom=166;dl=1;dr=1;dt=1;z=3};
divStatusHost={cls="custom";text="状态与操作";left=646;top=136;right=940;bottom=166;dr=1;dt=1;z=4};
statusHost={cls="custom";left=646;top=176;right=940;bottom=430;db=1;dr=1;dt=1;edge=1;z=6};
stepsHost={cls="custom";left=24;top=58;right=940;bottom=120;dl=1;dr=1;dt=1;z=2};
timelineHost={cls="custom";left=24;top=176;right=620;bottom=560;db=1;dl=1;dr=1;dt=1;z=5}
)
/*}}*/
var divFlow = AntdUI.Divider(winform.divFlowHost);
var divLog = AntdUI.Divider(winform.divLogHost);
var divStatus = AntdUI.Divider(winform.divStatusHost);
var steps = AntdUI.Steps(winform.stepsHost);
steps.Gap = 16;
steps.MilestoneMode = true;
steps.MilestoneCurrentCompleted = true;
steps.MilestoneTimeFormat = "MM-dd HH:mm";
var makeStep = function(id,title,subTitle,description,day,hour,minute){
var item = AntdUI.StepsItem(title,subTitle,description);
item.ID = id;
item.Tag = id;
item.MilestoneTimePoint = System.DateTime(2026,7,day,hour,minute,0);
return item;
}
steps.Items.Add(makeStep("accept","受理","已完成","服务台确认告警并创建工单",6,9,0));
steps.Items.Add(makeStep("diagnose","诊断","进行中","工程师分析日志与监控指标",6,9,20));
steps.Items.Add(makeStep("repair","修复","待开始","执行修复脚本或切换备用节点",6,10,10));
steps.Items.Add(makeStep("verify","验证","待开始","复测业务链路并观察告警",6,11,0));
steps.Items.Add(makeStep("archive","归档","待开始","整理复盘记录并关闭工单",6,11,30));
var timeline = AntdUI.Timeline(winform.timelineHost);
timeline.Gap = 16;
var alert = AntdUI.Alert(winform.statusHost);
alert.Icon = AntdUI.TType.Info;
alert.TextTitle = "流程准备就绪";
alert.Text = "点击右下角按钮推进工单;点击步骤或时间轴项可查看详情。";
alert.CloseIcon = false;
alert.BorderWidth = 1;
alert.Radius = 8;
var btnPrev = AntdUI.Button(winform.btnPrevHost);
btnPrev.Shape = AntdUI.TShape.Round;
var btnNext = AntdUI.Button(winform.btnNextHost);
btnNext.Shape = AntdUI.TShape.Round;
btnNext.Type = AntdUI.TTypeMini.Primary;
var btnError = AntdUI.Button(winform.btnErrorHost);
btnError.Shape = AntdUI.TShape.Round;
btnError.Type = AntdUI.TTypeMini.Error;
var btnDone = AntdUI.Button(winform.btnDoneHost);
btnDone.Shape = AntdUI.TShape.Round;
btnDone.Type = AntdUI.TTypeMini.Success;
var stageTitles = ["受理","诊断","修复","验证","归档"];
var current = 1; // 0 基:当前为“诊断”
var hasError = false;
var logIndex = 0;
var addLog = function(title,description,typ){
logIndex++;
var item = AntdUI.TimelineItem(tostring(time(),"%H:%M:%S") + " " + title,description);
item.ID = "log-" + logIndex;
item.Tag = title;
item.Type = typ;
timeline.Items.Add(item);
return item;
}
var applyState = function(){
steps.Current = current;
if(hasError){
steps.Status = AntdUI.TStepState.Error;
alert.Icon = AntdUI.TType.Error;
alert.TextTitle = "当前阶段异常:" + stageTitles[current + 1];
}
elseif(current >= (#stageTitles - 1)){
steps.Status = AntdUI.TStepState.Finish;
alert.Icon = AntdUI.TType.Success;
alert.TextTitle = "流程已完成";
}
else{
steps.Status = AntdUI.TStepState.Process;
alert.Icon = AntdUI.TType.Info;
alert.TextTitle = "当前阶段:" + stageTitles[current + 1];
}
alert.Text = string.concat(
"Current = ",current,"(0 基),展示给用户为第 ",current + 1," 步。",'\n',
"时间轴记录数:",timeline.Items.Count,"。可继续推进、回退或标记异常。"
);
btnPrev.Enabled = current > 0;
btnNext.Enabled = current < (#stageTitles - 1);
btnDone.Enabled = current < (#stageTitles - 1);
}
addLog("工单受理","系统收到 CPU 使用率连续 10 分钟超过阈值的告警。",AntdUI.TTypeMini.Success);
addLog("开始诊断","工程师正在核对最近发布记录与慢查询日志。",AntdUI.TTypeMini.Primary);
btnNext.Click = function(sender,e){
if(current < (#stageTitles - 1)){
current++;
hasError = false;
addLog("推进到" + stageTitles[current + 1],"流程进入下一阶段,等待责任人处理。",AntdUI.TTypeMini.Primary);
applyState();
}
}
btnPrev.Click = function(sender,e){
if(current > 0){
current--;
hasError = false;
addLog("回退到" + stageTitles[current + 1],"需要补充前一阶段信息,流程已回退。",AntdUI.TTypeMini.Warn);
applyState();
}
}
btnError.Click = function(sender,e){
hasError = true;
addLog("阶段异常:" + stageTitles[current + 1],"发现处理结果不符合预期,需人工介入。",AntdUI.TTypeMini.Error);
applyState();
}
btnDone.Click = function(sender,e){
current = #stageTitles - 1;
hasError = false;
addLog("工单完成","业务指标恢复正常,复盘记录已归档。",AntdUI.TTypeMini.Success);
applyState();
}
steps.ItemClick = function(sender,e){
var item = e.Item;
alert.Icon = AntdUI.TType.Info;
alert.TextTitle = "步骤:" + item.Title;
alert.Text = item.Description;
}
timeline.ItemClick = function(sender,e){
var item = e.Item;
alert.Icon = AntdUI.TType.Info;
alert.TextTitle = "日志:" + item.Text;
alert.Text = item.Description;
}
applyState();
winform.show();
win.loopMessage();
Steps.Current 与 steps.Items 等 .NET 集合都按 0 基索引理解;aardio 业务数组仍是 1 基。Steps.Status 表示当前步骤状态,常用 AntdUI.TStepState.Process/Finish/Error。Timeline 适合追加处理日志、审批记录、发布记录;它不替代 Steps 的当前流程状态。StepsItem.ID/Tag 与 TimelineItem.ID/Tag 可保存业务 key,点击事件中可用于回查业务数据。custom 宿主,再用 AntdUI.Control(winform.host) 填充宿主;不要把大量 .NET SetBounds 绝对布局写成普通窗口模板。