目录 · 第 07 章4 卷 12 章
第 07 章 · 卷二 搞懂 AI 怎么工作
Agent、上下文与工作流编排
什么时候让模型自己决定下一步,什么时候用固定流程兜住。
无人机实战平台已有设备接入、航线规划、任务下发、遥测回传和告警处置能力。Copilot 需要把用户的自然语言目标转换为可执行的巡检任务,并支持人工确认、飞行监控和报告生成。技术栈包括 Java 21、Spring Boot 3、Spring AI、Spring AI Alibaba、PostgreSQL、Redis、RocketMQ、Milvus、MinIO、Vue 3、Cesium 和 SSE。
使用 Agent Framework 承担智能决策,使用 Graph 管理多步骤执行流程。通过持久化任务状态、人工审批、上下文管理和错误恢复,控制模型的执行范围。以下类名、接口、表结构及代码均为方案设计,不代表现有项目已经实现。
暂无,本文只做方案设计。
1要解决的问题
复杂任务不是调用一次大模型就能完成的。
用户在三维地图上圈选一块区域,说:“这块地今天巡一遍消防通道。”
系统需要完成一连串工作:
- 理解用户目标,提取巡检区域、时间和巡检对象。
- 查询附近可用的无人机、机场、电量和设备状态。
- 检查空域限制、天气条件及任务执行约束。
- 根据区域和设备能力规划航线。
- 检查航线是否可执行,设备是否满足任务要求。
- 生成任务草稿,等待用户确认。
- 确认后下发任务,跟踪遥测和视觉告警。
- 发现异常时进入相应的处置流程,结束后生成报告。
这些步骤存在依赖关系。没有设备,不能直接下发任务;没有通过空域检查,不能执行航线;用户没有确认,不能因为模型认为方案合理就直接起飞。
真正要解决的问题是:让模型负责理解和有限决策,让程序负责流程、状态和执行边界。
这里有四个不同层次的能力。
普通 LLM 调用:输入一段文本,模型返回一段文本。例如解释某个告警的含义。模型不会自动查询设备,也不会因为回答中提到了航线就真的规划航线。
Tool Calling:模型决定调用哪个工具,并按工具定义提供参数。例如调用 queryAvailableDrones 查询设备。工具由 Java 程序实际执行,模型只负责提出调用请求。一次 Tool Calling 不等于完整的 Agent。
Agent:模型可以根据当前结果,决定下一步调用什么工具,并根据工具结果继续判断。例如发现一架无人机电量不足后,改查其他设备。它通常包含多轮模型调用和工具调用。
Workflow:程序提前定义步骤、分支和状态流转。例如必须先查设备、再查空域、再规划航线、再等待人工确认。模型可以参与单个节点,但不能随意跳过程序规定的步骤。
一次巡检任务可以同时使用四者:LLM 解析用户意图,Tool Calling 查询设备,Agent 在设备不足时寻找替代方案,Workflow 控制空域校验、审批和任务下发。
它们不是四种互斥的产品。它们分别解决文本生成、工具调用、动态决策和流程控制的问题。
2在整个系统中的位置
Copilot 位于现有业务平台之上,调用现有能力,而不是重新实现一套无人机控制系统。
交互层
Vue 3 + Cesium · 地图圈选 · 对话 · 审批 · SSE 状态推送
Copilot 应用层
意图解析 · Agent 决策 · Graph 编排 · 上下文管理 · 权限校验
业务工具层
设备查询 · 空域检查 · 航线规划 · 任务草稿 · 任务下发 · 告警处置
现有业务系统与数据层
设备服务 · 飞行任务服务 · PostgreSQL · Redis · RocketMQ · MinIO
各部分职责需要分清。
- Vue 3 和 Cesium 负责接收用户输入、展示地图和航线、显示任务状态以及提供人工确认入口。
- Copilot 应用层负责组织模型调用、执行流程、上下文和权限检查。
- 业务工具层将模型的意图转换为已有业务接口能够理解的请求。
- 现有业务系统负责真正的设备控制、任务执行和遥测处理。
例如,模型可以请求“创建巡检任务草稿”,但不能直接拼接数据库 SQL,也不能直接向无人机发送飞控指令。Java 服务需要验证参数、用户权限、设备状态和任务状态,再调用对应业务服务。
任务状态应以 PostgreSQL 等持久化数据为准。Redis 可以保存短期会话数据和运行期缓存,RocketMQ 可以传递异步任务事件。不能把一次模型对话的内存当作任务执行记录。
3总体设计
本章采用“固定主流程 + 局部 Agent”的设计。
固定主流程负责安全边界和业务顺序。Agent 只在需要动态判断的节点里工作。例如设备不足时,Agent 可以分析原因、查询替代设备;但它不能决定跳过空域检查,也不能跳过人工审批直接起飞。
3.1 Agent 执行循环
- 接收用户请求获取用户指令、地图圈选区域和会话标识
- 意图解析提取巡检目标、时间、区域和约束
- 读取当前状态加载任务进度、设备查询结果和剩余执行预算
- 模型决策根据当前状态决定调用哪个允许使用的工具
- 工具执行Java 服务校验参数、权限和业务条件后执行工具
- 写入执行结果更新 Graph 状态,记录工具结果和任务事件
- 检查执行条件判断是否完成、需要重试、需要人工介入或应该终止
- 继续决策未完成且允许继续时,再次进入模型决策
- 返回执行结果返回任务草稿、等待审批、执行失败或任务完成状态
这条循环不是无限运行的。每轮执行都需要检查允许调用的工具、最大迭代次数、超时、剩余模型调用预算和当前任务状态。
模型提出调用请求后,Java 服务先做校验,再执行操作。工具返回结果后,系统更新状态,再决定是否进入下一轮。
3.2 分层职责
建议把实现拆成四个部分。
| 组件 | 主要职责 |
|---|---|
CopilotAgentService | 调用模型,完成有限范围内的动态决策 |
InspectionGraphFactory | 定义节点、条件分支、暂停点和状态流转 |
ContextService | 加载短期对话、长期偏好和当前任务所需上下文 |
InspectionToolService | 封装设备、空域、航线和任务等业务接口 |
这些名称是建议的应用层类名,不是 Spring AI Alibaba 自带的固定类名。
3.3 Agent Framework 与 Graph 的分工
Spring AI Alibaba 的 Agent Framework 面向 Agent 的构建与运行,关注模型如何决策、如何使用工具,以及如何组织 Agent 的行为。
Graph 面向有状态的流程编排,关注节点之间怎么连接、什么条件下走哪个分支、执行中断后如何恢复。具体 API 和持久化能力需要根据项目锁定的 Spring AI Alibaba 版本确认,不能把本文的业务类名直接当成框架 API。
在这个项目中,可以这样划分:
- Agent Framework: 负责设备替代方案分析、工具选择、有限的多轮决策。
- Graph: 负责意图解析、设备检查、空域检查、航线校验、人工审批和任务下发的整体流程。
- 业务服务: 负责设备查询、空域校验、任务创建等真实业务操作。
- 上下文服务: 负责给模型提供当前步骤真正需要的信息。
不要让 Agent 同时承担全部流程控制。否则模型一旦误判,可能跳过关键步骤,系统也很难精确恢复到中断前的业务状态。
4完整执行链路
以用户圈选区域后发起消防通道巡检为例。
4.1 正常执行链路
Graph 接收请求后,先校验地图区域和用户权限,再解析自然语言目标。意图解析的结果需要结构化,例如:
{
"missionType": "FIRE_LANE_INSPECTION",
"areaId": "area-001",
"requestedAt": "2026-10-29",
"requireHumanApproval": true
}这是示例数据,不是实际运行记录。真实系统还应保存地图几何范围、坐标系、时间约束和来源信息。
后续节点按顺序执行:
query_devices:查询设备位置、在线状态、电量和载荷能力。check_airspace:检查目标区域及计划航线涉及的空域约束。plan_route:根据设备能力和区域生成航线。validate_plan:检查航线、设备、任务约束是否满足要求。create_draft:生成任务草稿,保存航线版本和校验结果。human_approval:暂停执行,等待用户确认。dispatch_task:重新检查关键条件,调用现有任务服务下发。monitor_mission:接收任务事件、遥测和视觉告警。generate_report:汇总执行记录、异常和证据,生成报告。
其中,任务下发不是“用户确认时直接执行一条命令”。审批通过后,还要检查设备是否仍在线、空域条件是否仍有效、任务草稿是否仍是当前版本。
4.2 分支:设备不够 → 换机场 → 重新规划
假设目标区域附近只有一架可用无人机,但它无法满足任务的续航要求。系统不能把“不够用”的设备硬塞进任务。
- query_devices查询候选无人机及机场
- check_capacity检查数量、续航、载荷和任务覆盖能力
- capacity_sufficient判断现有设备是否满足约束
- use_current_base满足条件则进入空域检查
- find_alternative_base不满足则查询其他机场和候选设备
- validate_alternative检查替代机场的设备能力、可达性和使用权限
- alternative_available判断是否找到满足约束的替代方案
- replan_route有可用替代方案则重新规划航线
- revalidate_plan重新校验航线、空域和任务约束
- human_approval生成新版本草稿,等待人工确认
- manual_intervention无可用替代方案则暂停并请求用户调整条件
这里有几个容易出错的地方。
换机场后必须重新规划。 机场位置发生变化,航程、续航消耗、航线覆盖和返航条件都可能变化。不能复用原航线后只修改一个机场字段。
替代方案需要有明确的评分和约束。 Agent 可以提出候选机场,但最终选择要受设备能力、空域、距离、权限等业务规则限制。硬约束不满足的方案必须排除,不能因为模型觉得合理就放行。
重新规划必须生成新版本。 例如 planVersion=2。原草稿和原航线继续保留,用于审计和问题追踪。新草稿通过完整校验后,才进入人工审批。
找不到替代方案时要停止。 系统返回“当前设备无法满足任务要求”,并说明缺少什么条件。用户可以调整区域、时间或任务范围,不允许无限循环查找。
4.3 执行状态与错误恢复
建议把流程状态和无人机业务状态分开管理。
| 流程状态 | 含义 |
|---|---|
RUNNING | Graph 正在执行 |
WAITING_APPROVAL | 等待人工审批 |
WAITING_RESOURCE | 等待设备或其他资源 |
PAUSED | 人工暂停,等待恢复 |
FAILED | 执行失败,需要处理 |
CANCELLED | 已取消 |
COMPLETED | 流程完成 |
无人机任务本身还需要自己的状态,例如 DRAFT、APPROVED、DISPATCHED、IN_FLIGHT、SUCCEEDED 和 ABORTED。两套状态不能混为一谈:Graph 进入 COMPLETED,可能表示“草稿创建流程完成”,并不代表无人机已经飞行结束。
恢复时,系统从持久化状态读取当前节点和任务版本,确认上一步是否已经产生业务副作用,再决定继续还是补偿。
例如,任务下发接口超时,不代表下发失败。系统应先通过任务 ID 或幂等键查询下发结果,避免重试造成重复任务。
5技术选型与原理
5.1 Agent 与固定工作流怎么选
| 对比项 | Agent 动态决策 | 固定 Workflow |
|---|---|---|
| 执行路径 | 根据上下文和工具结果选择下一步 | 由程序预先定义 |
| 适合场景 | 设备替代、告警分析、复杂问题诊断 | 空域检查、审批、下发、报告生成 |
| 灵活性 | 高,可以处理未预设的组合情况 | 路径相对固定,行为容易预测 |
| 可测试性 | 需要覆盖模型输出和工具组合 | 可以针对节点、分支做确定性测试 |
| 主要风险 | 错误选择工具、重复调用、推理偏离目标 | 流程僵化,遇到新情况需要增加分支 |
| 故障恢复 | 需要结合工具记录和业务状态判断 | 可以按已保存的节点状态恢复 |
| 安全控制 | 必须限制工具权限和调用范围 | 可在节点和边上设置明确约束 |
| 本项目用途 | 分析设备不足的原因,提出替代方案 | 控制校验、审批、下发及结束流程 |
判断标准很直接:结果不确定、需要根据新信息选择路径的步骤,可以使用 Agent;执行顺序明确、涉及安全或不可逆操作的步骤,优先使用固定工作流。
即使采用 Agent,也应该通过工具白名单、参数校验和预算限制约束它。即使采用固定工作流,也可以在某个节点调用大模型完成意图识别或告警解释。
5.2 Graph 为什么适合长流程
普通方法调用通常运行在一次请求里。无人机任务却可能跨越多分钟甚至更长时间,还可能等待用户审批、等待设备恢复或接收异步告警。
Graph 可以把任务拆成多个有输入、有输出的节点,通过条件边控制后续路径。配合持久化检查点,可以把“执行到了哪里”从进程内存转为可恢复的状态。
建议将节点设计成小而明确的业务步骤:
- 输入:从共享状态中读取必要字段。
- 执行:调用模型或业务服务。
- 输出:返回本节点产生的状态变更。
- 异常:区分可重试错误、业务拒绝和需要人工处理的错误。
节点不要直接修改一大堆无关字段,也不要把整段历史对话传给每一个节点。
5.3 MCP 解决什么问题
MCP(Model Context Protocol)是一种让 AI 应用以统一协议发现和调用外部工具、资源的方式。
在本项目中,如果无人机平台需要接入多个独立系统,例如第三方空域查询服务、企业知识库或外部资产平台,可以考虑把相应能力封装为 MCP Server,让支持 MCP 的客户端按统一方式发现和调用工具。
但 MCP 不是所有工具的必经通道。
| 工具类型 | 建议方式 | 原因 |
|---|---|---|
| 本服务内部的设备查询 | 直接调用 Java Service | 调用简单,类型约束清晰 |
| 本平台的航线规划接口 | 业务工具封装 | 便于做权限、事务和参数校验 |
| 独立部署的外部系统 | 视集成需求使用 MCP | 统一跨进程工具接入方式 |
| 企业知识库检索 | 直接集成或 MCP 均可 | 取决于现有检索服务和复用范围 |
| 起飞、返航等高风险操作 | 受控业务服务 | 必须有独立的权限和安全校验,不能因采用 MCP 而放宽限制 |
MCP 解决的是工具接入协议问题,不会自动解决 Agent 的规划、Graph 的状态持久化、权限审批或错误恢复。无论工具通过哪种方式接入,真正执行操作的服务都必须执行自己的安全校验。
6关键数据结构与代码
6.1 Graph 状态定义
Graph 的状态只保存执行过程中需要共享的信息。设备列表、航线版本、审批结果等结构化数据应有明确字段,不能全部塞进一个 String context。
下面使用 Java 21 风格展示业务状态模型。InspectionState 和节点类是目标设计中的应用层类型,并非框架内置类。
public enum FlowStatus {
RUNNING, WAITING_APPROVAL, WAITING_RESOURCE,
PAUSED, FAILED, CANCELLED, COMPLETED
}
public record InspectionRequest(
String missionType,
String areaId,
String userId,
String requestedAt
) {}
public record DeviceCandidate(
String deviceId,
String airportId,
boolean online,
double batteryPercent
) {}
public record RoutePlan(
String routeId,
int planVersion,
String deviceId,
String airportId
) {}
public record InspectionState(
String executionId,
String conversationId,
InspectionRequest request,
FlowStatus status,
String currentNode,
int iteration,
int planVersion,
List<DeviceCandidate> candidates,
RoutePlan routePlan,
String approvalId,
String errorCode,
String errorMessage
) {}生产实现还要增加空域校验结果、租户标识、状态版本、幂等键和时间戳。电量等字段也应采用平台实际的单位和数据类型,不能仅靠模型提供的数值判断设备是否可用。
6.2 节点定义
节点的核心职责是读取状态、执行单一业务步骤、返回状态变更。以下为简化的 Java 伪实现,便于说明结构,不是可直接编译的 Spring AI Alibaba Graph API 示例。
public interface InspectionNode {
String name();
InspectionState execute(InspectionState state);
}
public class QueryDevicesNode implements InspectionNode {
private final DeviceService deviceService;
public QueryDevicesNode(DeviceService deviceService) {
this.deviceService = deviceService;
}
@Override
public String name() {
return "query_devices";
}
@Override
public InspectionState execute(InspectionState state) {
var candidates = deviceService.findCandidates(
state.request().areaId()
);
return new InspectionState(
state.executionId(),
state.conversationId(),
state.request(),
FlowStatus.RUNNING,
name(),
state.iteration(),
state.planVersion(),
candidates,
state.routePlan(),
state.approvalId(),
null,
null
);
}
}实际项目可以用不可变状态对象或框架支持的状态更新机制,避免节点之间无约束地修改共享数据。
条件分支应该由程序根据明确的业务结果判断。例如:
public String nextNode(InspectionState state) {
if (state.status() == FlowStatus.CANCELLED) {
return "end";
}
if (state.candidates().isEmpty()) {
return "find_alternative_base";
}
if (state.routePlan() == null) {
return "plan_route";
}
return "validate_plan";
}这段代码只展示分支思想。正式实现还要检查候选设备是否满足续航和载荷要求,不能把“候选列表非空”等同于“设备足够”。
Graph 的节点和条件边应在图构建阶段注册。运行时由 Graph 执行节点、更新状态、选择下一条边。Agent 可以在 find_alternative_base 等节点内进行有限的动态决策。
6.3 记忆与任务状态分别存在哪里
这里有三类信息,不能混在一起。
| 类型 | 保存位置 | 内容与用途 |
|---|---|---|
| 短期上下文 | Redis、当前会话存储 | 最近几轮对话、当前轮次引用、临时摘要 |
| 长期偏好 | PostgreSQL | 用户明确设置的常用巡检方式、默认报告格式、偏好机场等 |
| 任务状态 | PostgreSQL | 执行 ID、当前节点、任务状态、航线版本、审批记录和错误信息 |
Milvus 可以存储文档向量,用于检索操作手册、设备说明和处置规程。它不是用户偏好或任务状态的权威存储。
MinIO 可以保存航线文件、图片、视频和巡检报告等对象。数据库保存对象引用、文件校验信息和关联任务 ID。
建议至少设计以下表:
copilot_conversation:会话基本信息。copilot_message:对话消息及必要的结构化元数据。copilot_user_preference:用户长期偏好。copilot_execution:Graph 执行实例及当前状态。copilot_execution_checkpoint:可恢复的执行检查点。copilot_execution_event:节点执行、工具调用、审批及错误事件。copilot_approval:人工审批记录。
Redis 中的缓存可以过期,但不能因为缓存过期就丢失尚未完成的任务。任务恢复必须以持久化状态为依据。
6.4 超长上下文怎么处理
大模型的上下文窗口不是越大越好。对话越来越长时,应按用途筛选信息,而不是把全部聊天记录持续追加进去。
建议采用三步处理。
第一步:保留当前任务必需字段。 任务 ID、区域几何范围、设备约束、当前航线版本、空域校验结果、审批状态和待执行节点,都应从结构化状态重新加载。
第二步:对历史对话做摘要。 保留用户目标、已确认条件、已经尝试的方案、失败原因和未解决的问题。普通闲聊可以压缩,不能把尚未确认的推测写成用户已经确认的事实。
第三步:按节点构造上下文。 设备查询节点只需要区域、设备能力要求和当前任务状态;告警分析节点需要告警信息、相关遥测和适用的操作规程。无需每次把所有历史消息都传给模型。
可以给每次模型调用配置上下文预算:
public record ContextBudget(
int maxInputTokens,
int maxOutputTokens,
int maxIterations,
int maxToolCalls
) {}这些字段表示设计上的预算参数,不代表当前模型的实际限制。具体值应根据所选模型的上下文窗口、工具数量和业务测试结果确定。
需要注意,摘要不能代替原始证据。关键操作记录、审批人、审批时间、工具返回的业务 ID、空域检查结果及原始告警引用必须保留。模型生成的摘要只能帮助理解,不能作为任务是否执行成功的唯一依据。
6.5 暂停、恢复与取消
人工介入不能只在前端隐藏一个“继续”按钮。后端必须有可持久化的状态转换。
- 暂停: 将执行实例转为
PAUSED,记录当前节点和检查点。若任务已在飞行,暂停 Graph 不等于暂停无人机,飞行安全由独立业务控制流程负责。 - 恢复: 根据
executionId加载检查点,验证任务未取消、状态版本匹配、依赖资源仍可用,再从安全恢复点继续。 - 取消: 记录取消请求,阻止后续普通节点继续执行。若无人机已经起飞,还必须走现有任务服务的取消或安全处置流程,不能只把数据库状态改成
CANCELLED。 - 审批: 持久化审批人、审批时间、审批结果和对应的
planVersion。审批旧版本不能自动授权新版本。
推荐的持久化顺序是:先记录节点开始事件,再执行可重试的查询或规划操作,获得结果后保存状态和检查点。对于下发任务等有外部副作用的操作,还需要幂等键和结果核对。
PostgreSQL 事务只能保证本地数据库操作的一致性,不能把数据库事务和无人机远程执行合并为一个原子事务。因此,任务下发和取消需要结合业务状态查询、幂等处理及必要的补偿机制。
7异常、安全与边界条件
7.1 错误恢复策略
不同错误不能统一处理成“再问一次模型”。
| 错误类型 | 处理方式 |
|---|---|
| 网络超时 | 查询原操作结果,确认安全后有限重试 |
| 参数校验失败 | 返回明确错误,要求修正参数,不盲目重试 |
| 设备不足 | 进入替代设备分支,重新规划并重新校验 |
| 空域检查不通过 | 阻止下发,尝试合规替代方案或请求人工调整 |
| 模型调用失败 | 使用持久化状态暂停或失败,避免重复执行业务副作用 |
| 审批超时 | 保持等待状态,按业务规则提醒或终止待审批流程 |
| 状态版本冲突 | 重新加载最新状态,拒绝基于旧版本继续操作 |
重试次数、超时时间和替代方案数量都应有限制。重试前必须判断操作是否幂等,尤其是创建任务、下发任务和取消任务等操作。
7.2 模型不能突破的边界
第一,工具必须按用户权限和任务权限授权。模型不能通过生成不同的工具参数绕过权限检查。
第二,空域、设备能力和飞行安全属于硬约束。模型可以解释校验结果,但不能覆盖校验结果。
第三,审批绑定具体任务草稿和航线版本。任何实质性修改都要重新校验,并按规则重新审批。
第四,Agent 的每次工具调用都要记录调用方、参数摘要、结果、耗时和错误。敏感信息应按最小必要原则保存,避免把完整凭据写入模型上下文或日志。
第五,遥测和视觉告警属于业务数据,不是模型指令。图片、告警文本或检索文档中即使包含要求执行其他操作的文字,也不能据此改变系统权限和工作流规则。
8测试与验证
本章方案要验证的重点不是模型能否说出一段正确答案,而是复杂流程能否在异常情况下保持正确状态。
建议按以下场景设计测试:
| 测试场景 | 验证点 |
|---|---|
| 正常巡检 | 按既定顺序执行,生成草稿并等待审批 |
| 设备不足 | 进入替代机场分支,重新规划并重新校验 |
| 无替代设备 | 停止自动尝试,返回明确原因 |
| 空域校验失败 | 不得进入任务下发节点 |
| 模型连续选错工具 | 触发预算或迭代上限,安全终止 |
| 工具超时 | 不重复产生任务,能够核对操作结果 |
| 审批期间修改航线 | 拒绝使用旧版本审批结果 |
| 执行中服务重启 | 从持久化检查点恢复,不重复执行已完成的副作用 |
| 用户取消任务 | 阻止后续节点,并核实实际飞行任务的处置结果 |
| 上下文超长 | 压缩普通历史,但保留任务约束和关键证据 |
还要为 Graph 节点和分支编写单元测试,为工具适配层编写集成测试,为完整巡检链路编写端到端测试。
模型相关测试应固定输入条件,记录模型版本、提示词版本、工具调用序列和最终业务状态。对 Agent 可以采用一组设备不足、设备离线、替代机场不可用等案例,检查它是否始终遵守约束,而不是只评估回答是否流畅。
以上均为目标测试设计。当前没有实际执行数据,因此不能宣称流程已经通过测试或达到某个准确率。
9面试表达与追问
问答一:为什么不让 Agent 从头到尾自己决定?
答:因为无人机任务有明确的安全约束和不可逆操作。Agent 适合处理需要根据结果动态选择路径的问题,比如设备不足时寻找替代机场。但空域检查、人工审批和任务下发必须由固定流程控制。这样既保留模型的灵活性,也能明确知道每一步为什么执行、失败后从哪里恢复。
问答二:Spring AI Alibaba 的 Agent Framework 和 Graph 有什么区别?
答:我把 Agent Framework 理解为 Agent 的构建与运行能力,重点是模型决策和工具使用;Graph 重点是把多个步骤组织成有状态的流程,定义节点、分支和恢复点。实际项目中,我会用 Agent 处理局部的动态决策,用 Graph 控制整条巡检链路。具体 API 要根据项目采用的框架版本确定。
问答三:用户在审批节点关闭页面,系统怎么继续执行?
答:我不会把执行状态只放在前端或 Java 进程内存里。后端会持久化执行实例、当前节点、检查点和审批状态。用户重新进入页面时,根据 executionId 查询真实状态。用户恢复操作时,后端会重新检查任务是否取消、航线版本是否变化、设备和空域条件是否仍有效。只有满足恢复条件,才继续执行。审批等待期间不会因为页面关闭就自动下发任务。