# Steps + Timeline 工单流转面板

本页给出一个流程状态面板示例，把 `Steps` 与 `Timeline` 组合起来：上方步骤条表示当前阶段，下方时间轴记录处理日志，右侧按钮驱动流程推进、回退、异常与完成。

> 重点：`Steps.Current` 使用 .NET/AntdUI 习惯从 `0` 开始计数；而 aardio 数组从 `1` 开始，所以用业务数组取标题时通常写为 `stageTitles[current + 1]`。

## 完整示例

```aardio
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，点击事件中可用于回查业务数据。
- 复杂页面建议像本例一样使用 aardio 设计器放置多个语义化 `custom` 宿主，再用 `AntdUI.Control(winform.host)` 填充宿主；不要把大量 .NET `SetBounds` 绝对布局写成普通窗口模板。

## 相关文档

- [Steps 步骤条](../controls/navigation/steps.html)
- [Timeline 时间轴](../controls/data-display/timeline.html)
