设计一个简单的，由三个节点组成的流程：`Draft -> Review -> Confirm`。此示例，也可适用于 AI 流程等用户输入。

### 1、定义订单状态

```java
@Data
@AllArgsConstructor
public static class OrderState {
    String orderId;
    String draftContent;
    boolean isApproved;
    String finalMessage;
}
```

### 2、定义节点任务组件


* Draft 起草

```java
public class Draft implements TaskComponent{
    @Override
    public void run(FlowContext ctx, Node n) throws Throwable {
        OrderState state = ctx.getAs("state");

        String draft = "订单 " + state.getOrderId() + " 的销售合同草稿已生成，总价 $10000，请审核。";
        System.out.println("Node 1: [生成草稿] 完成，内容: " + draft);
        state.setDraftContent(draft);
    }
}
```


* Review 审计

```java
public class Review implements TaskComponent{
    @Override
    public void run(FlowContext ctx, Node n) throws Throwable {
        OrderState state = ctx.getAs("state");

        if (!state.isApproved()) {
            System.out.println("Node 2: [人工审核] 订单草稿需要人工确认。");
            ctx.stop();
        } else {
            System.out.println("Node 2: [人工审核] 已通过外部系统确认，继续流程。");
        }
    }
}
```

* Confirm 确认

```java
public  class Confirm implements TaskComponent{
    @Override
    public void run(FlowContext ctx, Node n) throws Throwable {
        OrderState state = ctx.getAs("state");
        
        String finalMsg = "订单 " + state.getOrderId() + " 流程已完成，合同已发送。";
        System.out.println("Node 3: [最终确认] " + finalMsg);
        state.setFinalMessage(finalMsg);
    }
}
```

### 3、构建流图并运行和测试

（FlowContext:lastNodeId 需要 v3.8.0 后支持 ）为方便测试，下面使用硬编码方式。平常建议使用 yaml 编排（更适合所有角色：开发、测试、运维，领导）。

```java
@Slf4j
public class ControlFlowTest {
    @Test
    public void case1() {
        //硬编码构建流图，方便测试
        Graph graph = new GraphSpec("demo1").then(spec -> {
            spec.addActivity("n1").task(new Draft()).linkAdd("n2");
            spec.addActivity("n2").task(new Review()).linkAdd("n3");
            spec.addActivity("n3").task(new Confirm());
        }).create();

        /// ////////////
        FlowEngine flowEngine = FlowEngine.newInstance();
        OrderState initialState = new OrderState("o-1", null, false, null);

        FlowContext context = FlowContext.of(initialState.orderId).put("state", initialState);
        flowEngine.eval(graph, context);
        
        // 可以持久化 context.toJson() ，下次恢复使用 FlowContext.fromJson(json)
        Assertions.assertEquals("n2", context.lastNodeId());

        //模拟人工审核后
        initialState.setApproved(true);
        flowEngine.eval(graph, context);
        Assertions.assertEquals("n3", context.lastNodeId());
    }
}
```


### 4、运行效果

<img src="/img/7ca859fb2a4445fea888707426b1c3b5.png" width="700"/>