新增任务模板界面

This commit is contained in:
18086616529
2026-06-03 10:14:40 +08:00
parent 7382e85598
commit 5716c4e8ff
18 changed files with 3590 additions and 0 deletions
@@ -0,0 +1,638 @@
# 任务编排界面 · Workflow 编排设计说明
> 设计日期:2026-06-01
> 范围:任务编排页 → **Workflow 编排** Tab
> 状态:MVP 已实现,本文档与当前控件库参数定义同步
---
## 1. 设计目标
为调度人员提供可视化的任务流程编排能力:通过拖拽控件、连线、配置参数,完成 AGV 调度流程的设计,无需编写脚本。
设计原则:
- **所见即所得**:画布即流程,节点即步骤
- **分组清晰**:控件按业务语义分类,左侧一行简介即可理解用途
- **分支可辨**:涉及「成功/失败」「正常/超时」的节点,出口必须在视觉上可区分
- **参数克制**:只展示当前步骤需要的字段,随选项变化动态显隐
---
## 2. 页面结构
```
┌──────────────────────────────────────────────────────────────────────────┐
│ 顶栏:流程名称 · 校验 · [删除选中][加载示例][导入][导出][清除画布] │
├────────────┬─────────────────────────────────────────┬───────────────────┤
│ 流程库 │ 流程画布 │ 参数配置 │
│ 控件库 │ │ │
│ 搜索 │ 节点 · 连线 · 缩放 · 平移 │ 选中节点的属性 │
│ 分组列表 │ │ │
└────────────┴─────────────────────────────────────────┴───────────────────┘
```
| 区域 | 宽度建议 | 职责 |
|------|----------|------|
| 流程库 | 约 220px(与控件库同列) | 管理多个已保存流程,新建 / 保存 / 切换 / 复制 / 删除 |
| 控件库 | 约 220px(流程库下方) | 浏览、搜索、拖拽控件到画布 |
| 流程画布 | 自适应 | 编排主工作区 |
| 参数配置 | 约 280px | 编辑当前选中节点或连线的属性 |
顶栏 **校验状态** 对流程完整性做即时提示(如缺少开始节点、分支未连接等),不打断编辑。
---
## 3. 控件库
### 3.1 分组与配色
| 分组 | 主色 | 控件 |
|------|------|------|
| 流程入口 | 绿色 | 开始、结束 |
| 调度动作 | 橙色 | 前往站点、执行动作、分配车辆 |
| 流程逻辑 | 紫色 | 条件分支、延时事件 |
| 事件与信号 | 蓝色 | 等待事件、通知事件 |
| 协议控制 | 青色 | 设备控制 |
### 3.2 控件卡片信息层级
每个控件卡片包含:
1. **名称**(主标题,一行)
2. **简介**(副标题,**仅一行**,超出省略)
不在控件库中展示长说明或技术协议细节;详细配置留给右侧参数面板。
### 3.3 控件简介一览
| 控件 | 类型编码 | 简介 |
|------|----------|------|
| 开始 | `start` | 流程起点(全局唯一) |
| 结束 | `end` | 流程终点 |
| 前往站点 | `gotoSite` | AGV 移动到目标站点 |
| 执行动作 | `executeAction` | 下发 VDA5050 单条动作指令 |
| 分配车辆 | `assignCar` | 为任务指定车辆或车型 |
| 条件分支 | `branch` | 条件成立与否走不同分支 |
| 延时事件 | `delay` | 等待指定秒数后继续 |
| 等待事件 | `waitEvent` | 等待事件触发,超时走另一路 |
| 通知事件 | `notify` | 调用接口推送 JSON 通知 |
| 设备控制 | `deviceControl` | Modbus 读等待或写输出 |
---
## 4. 画布节点
### 4.1 通用节点样式
- 白底圆角卡片,边框颜色与所属分组一致
- 左侧:一个输入连接点
- 右侧:一个输出连接点(结束节点无输出)
- 内容区:控件类型(小字)+ 用户自定义显示名(加粗)
选中态:蓝色外发光,与未选中节点明确区分。
### 4.2 双出口节点
**适用控件**:条件分支、等待事件
| 元素 | 规范 |
|------|------|
| 节点高度 | 高于普通节点,预留双出口空间 |
| 出口数量 | 右侧上下两个连接点 |
| 出口布局 | 标签与连接点同一行(flex 行布局),文字在左、Handle 在右,保证对齐 |
| 出口标签 | 节点内右侧展示文字标签 |
| 连线颜色 | 上方出口路径偏绿,下方出口路径偏红 |
| 连线标签 | 连线上标注出口含义 |
**出口标识(sourceHandle**
| 控件 | 上方出口 | 下方出口 |
|------|----------|----------|
| 条件分支 | `success`(成立) | `fail`(不成立) |
| 等待事件 | `triggered`(正常执行) | `timeout`(超时执行) |
---
## 5. 控件参数设计
### 5.1 前往站点
**用途**:指令 AGV 移动到指定站点。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 目标站点 | 文本 | 是 | 站点编号,如 S001 |
---
### 5.2 执行动作
**用途**:下发 VDA5050 协议中的单条 Action 指令(`actionId` 由运行时生成,不在编排界面配置)。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 动作类型 | 下拉 | 是 | 取货 / 放货 / 充电,默认「取货」 |
| 动作参数 | 多行文本 | — | JSON 数组,可选 |
**动作类型与导出值对照**
| 界面选项 | 导出值 `actionType` |
|----------|---------------------|
| 取货 | `pick` |
| 放货 | `drop` |
| 充电 | `startCharging` |
**动作参数示例**
```json
[{"key":"loadType","value":"pallet"}]
```
---
### 5.3 分配车辆
**用途**:为任务指定执行车辆或车辆类型。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 分配策略 | 单选 | 是 | 指定车辆 / 指定类型 |
| 车辆编号 | 文本 | 是* | 选择「指定车辆」时显示,如 C01 |
| 车辆类型 | 文本 | 是* | 选择「指定类型」时显示,如车型类名 |
\* 随分配策略切换,只展示对应字段。
**分配策略与导出值对照**
| 界面选项 | 导出值 `strategy` |
|----------|-------------------|
| 指定车辆 | `fixed` |
| 指定类型 | `byType` |
---
### 5.4 等待事件
**用途**:阻塞流程,直到指定事件发生或超时。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 事件名 | 文本 | 是 | 如 site.arrived |
| 超时(秒) | 数字 | — | 默认 60;填 0 表示不超时 |
**双出口语义**
| 出口位置 | 标签 | 含义 |
|----------|------|------|
| 上方(绿) | 正常执行 | 在超时前收到事件,沿此路径继续 |
| 下方(红) | 超时执行 | 超过设定秒数仍未收到事件,沿此路径处理 |
**设计建议用法**
- 正常执行 → 后续业务步骤(如送料完成通知)
- 超时执行 → 告警、重试、人工介入或结束流程
**校验提示**:设置了超时时间但未连接「超时执行」出口时,顶栏给出警告。
---
### 5.5 通知事件
**用途**:向外部系统推送通知,不阻塞主流程。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 接口地址 | 文本 | 是 | HTTP 接口 URL |
| 数据配置 | 多行文本 | 是 | JSON 格式请求体 |
| 消息 | 多行文本 | 否 | 运维界面可见的提示文案 |
| 级别 | 单选 | — | 信息 / 警告 / 错误,默认信息 |
**数据配置示例**
```json
{
"event": "delivery.complete",
"payload": {
"missionId": "M01",
"status": "ok"
}
}
```
---
### 5.6 条件分支
**用途**:根据条件表达式决定流程走向。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 条件表达式 | 多行文本 | 是 | 如 batterySoc > 0.2 |
**双出口语义**
| 出口位置 | 标签 | 含义 |
|----------|------|------|
| 上方(绿) | 成立 | 表达式结果为 true |
| 下方(红) | 不成立 | 表达式结果为 false |
---
### 5.7 延时事件
**用途**:阻塞流程指定时长后继续执行,单出口。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 延时(秒) | 数字 | 是 | 默认 5 |
---
### 5.8 设备控制
**用途**:通过 Modbus 协议读取设备信号(等待触发)或向设备写入输出值。
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 读写模式 | 下拉 | 是 | 读信号(接收)/ 写信号(输出),默认读 |
| 协议类型 | 下拉 | 是 | Modbus TCP / Modbus RTU |
| 连接地址 | 文本 | 是 | TCP 如 `10.0.2.30:502`RTU 如 `COM3,9600,8,N,1` |
| 寄存器地址 | 数字 | 是 | 如 40001 或 0(视驱动约定) |
| 数据类型 | 下拉 | 是 | 布尔 / Int16 / UInt16 / Int32 / Float32 |
**读模式额外字段**(选择「读信号」时显示):
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 触发条件 | 下拉 | 是 | 等于 / 不等于 / 大于 / 大于等于 / 小于 / 小于等于 / 值发生变化 |
| 轮询间隔 (ms) | 数字 | — | 默认 500 |
**写模式额外字段**(选择「写信号」时显示):
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 写入值 | 文本 | 是 | 如 `1` / `true` / `100` |
| 写入模式 | 下拉 | — | 持续写入 / 脉冲(写入后复位),默认持续写入 |
| 脉冲宽度 (ms) | 数字 | — | 写入模式为脉冲时有效,默认 500 |
| 写入后回读校验 | 开关 | — | 默认开启 |
---
## 6. 参数面板交互规范
| 规则 | 说明 |
|------|------|
| 标签置顶 | 字段名在输入框上方,必填项标红星 |
| 条件显隐 | 仅展示与当前选项相关的字段;切换选项时清理已隐藏字段的值 |
| 布尔控件 | 使用开关,显示「是 / 否」,禁止白字白底不可见 |
| 空状态 | 未选中节点时提示「选中画布上的节点以编辑参数」 |
| 显示名称 | 所有节点均可编辑显示名,独立于控件类型 |
| 无参节点 | 开始、结束节点无可配置业务参数,仅可改显示名 |
| 节点删除 | 参数面板底部提供「删除节点」按钮,二次确认后删除 |
| 连线选中 | 点击画布上的连线,右侧面板切换为连线详情(起点、终点、出口标签) |
---
## 6.1 删除节点与连线
### 选中方式
| 对象 | 操作 |
|------|------|
| 节点 | 点击节点,右侧显示参数面板 |
| 连线 | 点击连线,右侧显示连线详情;选中态连线加粗高亮 |
点击画布空白处取消选中。
### 删除方式
| 方式 | 节点 | 连线 | 说明 |
|------|------|------|------|
| 快捷键 | ✓ | ✓ | 选中后按 **Delete****Backspace**,立即删除,无需确认 |
| 顶栏「删除选中」 | ✓ | ✓ | 删除节点需二次确认;仅删连线时直接删除 |
| 参数面板「删除节点」 | ✓ | — | 二次确认后删除,关联连线一并移除 |
| 连线面板「删除连线」 | — | ✓ | 直接删除,无需确认 |
**规则**
- 删除节点时,与该节点相连的所有连线自动移除
- 删除连线不影响节点本身
- 删除后右侧面板回到空状态;草稿自动保存
---
## 7. 顶栏操作与校验
### 7.1 顶栏操作
| 操作 | 行为 |
|------|------|
| 流程名称 | 可编辑,标识当前流程 |
| 删除选中 | 删除当前选中的节点或连线;无选中时按钮禁用 |
| 加载示例 | 将内置「A区送料示例」加入流程库并切换编辑(不覆盖其他已保存流程) |
| 导入 | 从 JSON 文件导入流程,追加到**当前会话**流程库(支持单流程与流程库合集,见 11.5) |
| 导出 | 下载当前会话流程库内**全部流程**的合集 JSON(见 11.4 节) |
| 清除画布 | 二次确认后清空**当前流程**画布上的节点与连线 |
流程库仅保存在**当前浏览器会话内存**中(刷新页面会恢复为内置示例,除非通过「导入」重新载入)。编辑过程中会自动同步到内存流程库(约 400ms 防抖),便于切换多个流程;**持久化请使用顶栏「导出」下载 JSON 文件**。
### 7.1.1 流程库(多流程管理)
左侧面板顶部为 **流程库** 列表:
| 操作 | 说明 |
|------|------|
| + 新建 | 创建空白流程并切换为当前编辑对象 |
| 保存 | 将当前流程写入内存流程库(存在校验错误时阻止保存并提示) |
| 点击列表项 | 切换到该流程(切换前自动同步当前编辑到内存) |
| 复制 | 复制当前选中流程为「xxx(副本)」 |
| 删除 | 从库中移除该流程(至少保留 1 个) |
每个列表项显示流程名称与节点数量;当前编辑项高亮。
### 7.2 流程校验
顶栏实时展示校验结果:全部通过时显示绿色「校验通过」;存在问题则列出错误与警告,**不阻断编辑**。
| 级别 | 条件 |
|------|------|
| 错误 | 缺少「开始」节点 |
| 错误 | 存在多个「开始」节点 |
| 错误 | 「开始」节点未连接下游 |
| 警告 | 未添加「结束」节点 |
| 警告 | 「结束」节点没有上游连线 |
| 警告 | 中间节点处于孤立状态(无上游连线) |
| 警告 | 「等待事件」未连接「正常执行」出口 |
| 警告 | 「等待事件」设置了超时但未连接「超时执行」出口 |
保存时:若存在错误则阻止并提示;若仅有警告则允许保存并弹出警告条数。
---
## 8. 示例流程(A区送料)
用于演示双出口与通知节点的典型编排:
```
开始
→ 分配车辆(指定车辆 C01
→ 前往站点(S001
→ 执行动作(取货)
→ 等待到达(事件 site.arrived,超时 120 秒)
├─ 正常执行 → 送料完成通知 → 结束
└─ 超时执行 → 等待超时告警 → 结束
```
---
## 9. 视觉与主题注意事项
任务编排编辑器内部面板(控件库、画布区、参数配置)采用 **白底 + 深色文字**,与平台全局深色/紫色主题隔离,避免:
- 表单文字不可见
- 开关关闭态「否」与背景融为一体
- 下拉、输入框在浅色卡片上显示异常
节点、连线、标签颜色以 **绿 = 正向/成功/正常**、**红 = 异常/超时/不成立** 为语义约定,全页保持一致。
---
## 10. 后续扩展方向(设计预留)
- 流程版本管理与发布
- 与 Mission 实例管理的联动(编排 → 实例化)
- 控件库随插件任务类型扩展
- 画布缩略图、对齐辅助线、撤销重做
- 运行时执行态在画布上的高亮反馈
---
## 11. 导出的 JSON 数据示例
- **导出**:下载流程库合集 `workflow-catalog.json`,内含当前会话全部流程(结构见 11.4)。
### 11.1 数据结构说明
| 顶层字段 | 含义 |
|----------|------|
| `id` | 流程唯一标识 |
| `name` | 流程名称 |
| `version` | 流程版本号 |
| `viewport` | 画布视口位置与缩放 |
| `nodes` | 节点列表 |
| `edges` | 连线列表 |
**节点(nodes** 每条包含:
| 字段 | 含义 |
|------|------|
| `id` | 节点 ID |
| `type` | 控件类型(如 start、assignCar、waitEvent |
| `label` | 显示名称 |
| `position` | 画布坐标 |
| `params` | 该节点的参数配置 |
| `nextId` | 下一节点 ID(单出口 / 条件成立 / 正常执行);结束节点为 `null` |
| `failNextId` | 条件不成立时的下一节点 ID(仅条件分支) |
| `timeoutNextId` | 超时执行时的下一节点 ID(仅等待事件) |
**连线(edges** 每条包含:
| 字段 | 含义 |
|------|------|
| `id` | 连线 ID |
| `source` | 起始节点 ID |
| `target` | 目标节点 ID |
| `sourceHandle` | 出口标识(双出口节点必填,如正常执行、超时执行) |
| `label` | 连线标签(可选) |
### 11.2 完整示例(A区送料)
对应第 8 节示例流程的导出内容:
```json
{
"id": "wf-demo-001",
"name": "A区送料示例",
"version": 1,
"viewport": { "x": 0, "y": 0, "zoom": 1 },
"nodes": [
{
"id": "n1",
"type": "start",
"label": "开始",
"position": { "x": 60, "y": 200 },
"params": {},
"nextId": "n2"
},
{
"id": "n2",
"type": "assignCar",
"label": "分配车辆",
"position": { "x": 240, "y": 180 },
"params": {
"strategy": "fixed",
"carId": "C01"
},
"nextId": "n3"
},
{
"id": "n3",
"type": "gotoSite",
"label": "前往入库点",
"position": { "x": 460, "y": 180 },
"params": {
"siteId": "S001"
},
"nextId": "n4"
},
{
"id": "n4",
"type": "executeAction",
"label": "取货",
"position": { "x": 680, "y": 180 },
"params": {
"actionType": "pick",
"actionParameters": "[{\"key\":\"loadType\",\"value\":\"pallet\"}]"
},
"nextId": "n5"
},
{
"id": "n5",
"type": "waitEvent",
"label": "等待到达",
"position": { "x": 900, "y": 180 },
"params": {
"eventName": "site.arrived",
"timeoutSec": 120
},
"nextId": "n6",
"timeoutNextId": "n8"
},
{
"id": "n6",
"type": "notify",
"label": "送料完成通知",
"position": { "x": 1120, "y": 180 },
"params": {
"apiUrl": "http://127.0.0.1:8080/api/hook/notify",
"dataConfig": "{\"event\":\"delivery.complete\",\"message\":\"送料完成\"}",
"message": "送料完成",
"level": "info"
},
"nextId": "n7"
},
{
"id": "n7",
"type": "end",
"label": "结束",
"position": { "x": 1340, "y": 200 },
"params": {},
"nextId": null
},
{
"id": "n8",
"type": "notify",
"label": "等待超时告警",
"position": { "x": 1120, "y": 320 },
"params": {
"apiUrl": "http://127.0.0.1:8080/api/hook/notify",
"dataConfig": "{\"event\":\"wait.timeout\",\"message\":\"等待到达超时\"}",
"message": "等待到达超时",
"level": "warn"
},
"nextId": "n7"
}
],
"edges": [
{ "id": "e1", "source": "n1", "target": "n2" },
{ "id": "e2", "source": "n2", "target": "n3" },
{ "id": "e3", "source": "n3", "target": "n4" },
{ "id": "e4", "source": "n4", "target": "n5" },
{
"id": "e5",
"source": "n5",
"target": "n6",
"sourceHandle": "triggered",
"label": "正常执行"
},
{
"id": "e5t",
"source": "n5",
"target": "n8",
"sourceHandle": "timeout",
"label": "超时执行"
},
{ "id": "e6", "source": "n6", "target": "n7" },
{ "id": "e8", "source": "n8", "target": "n7" }
]
}
```
### 11.3 阅读要点
- 每个节点导出时会根据连线自动写入 **`nextId`**,执行引擎可直接按节点跳转,无需再解析 `edges`
- **等待事件**`nextId` = 正常执行下游,`timeoutNextId` = 超时执行下游。
- **条件分支**`nextId` = 条件成立下游,`failNextId` = 条件不成立下游。
- **结束节点**`nextId``null`
- `edges` 仍保留,便于还原画布布局;与 `nextId` 字段互为补充。
- **等待事件** 的两条出线通过 `sourceHandle` 区分:`triggered` 表示正常执行,`timeout` 表示超时执行。
- **条件分支** 的双出口同理:`success` 表示条件成立,`fail` 表示条件不成立。
- 节点的 `params` 只保存当前生效的字段;例如「分配车辆」在指定车辆策略下仅含 `strategy``carId`,不会出现无关的空字段。
- **执行动作** 的 `actionType` 存 VDA5050 枚举值(`pick` / `drop` / `startCharging`),界面下拉选项与之对应。
- `dataConfig``actionParameters` 等字段在 JSON 中以 **字符串** 形式存储 JSON 内容,导入时需按文本解析。
### 11.4 流程库合集导出(导出)
点击 **「导出」** 后,下载 `workflow-catalog.json`,包含流程库内每一个流程的完整定义(均已附带 `nextId`)。
```json
{
"catalogVersion": 3,
"exportedAt": "2026-06-01T12:00:00.000Z",
"workflows": [
{
"id": "wf-demo-001",
"name": "A区送料示例",
"version": 1,
"viewport": { "x": 0, "y": 0, "zoom": 1 },
"nodes": [ "..." ],
"edges": [ "..." ]
},
{
"id": "wf-1730000000000-1",
"name": "未命名流程",
"version": 1,
"nodes": [],
"edges": []
}
]
}
```
| 字段 | 含义 |
|------|------|
| `catalogVersion` | 流程库 schema 版本,与 localStorage 中一致 |
| `exportedAt` | 导出时间(ISO 8601 |
| `workflows` | 流程数组,每项结构与单流程导出相同 |
执行引擎或后端可遍历 `workflows` 加载多套模板;单流程导入可使用单流程 JSON 文件(结构见 11.2)。
### 11.5 导入 JSON
点击顶栏 **「导入」**,选择本地 `.json` 文件。系统自动识别以下格式并**追加**到流程库(不覆盖已有流程):
| 格式 | 识别条件 | 示例来源 |
|------|----------|----------|
| 单流程 | 顶层含 `nodes``edges` | 单流程 JSON 文件 |
| 流程库合集 | 顶层含 `workflows` 数组 | 「导出」生成的 `workflow-catalog.json` |
| 旧版 draft | 顶层含 `workflow` 对象 | 早期单流程草稿格式 |
**导入规则**
- 导入前会先保存当前正在编辑的流程
- 流程 `id` 与库内已有重复时,自动分配新 ID
- 节点上的 `nextId` / `failNextId` / `timeoutNextId` 会被忽略,画布连线以 `edges` 为准
- 导入完成后切换到**最后一个**导入的流程进行编辑
- 参数会按当前控件库 schema 规范化(补默认值、剔除无效字段)
- 存在校验警告时不阻断导入,顶栏会提示警告条数