Mermaid Swimlanes(泳道图)语法与实战指南:用 subgraph 表达"谁负责"的流程图
导读
泳道图(Swimlane Diagram)是 Mermaid 自 v11.16.0 起引入的实验性图类型(以 swimlane-beta 为起始关键字,语法仍可能在后续版本演进)。与普通流程图只回答"接下来发生什么"不同,泳道图通过纵向划分的"泳道"额外回答"这一步归谁负责"。本文基于仓库中的官方文档 swimlanes.md(渲染后的用户文档见 docs/syntax/swimlanes.md)并结合源码,完整讲解其声明方式、泳道/节点/连线语法、无障碍声明、专项配置项与布局引擎的实现原理。读完本文,你将能直接写出结构清晰的审批流、工单流转与跨团队交付流程,并了解该图类型背后"复用 flowchart 引擎、仅替换泳道布局"的架构设计。
什么是泳道图:按职责划分的过程图
泳道图把一条流程按"负责人"切开:每条泳道(lane)代表一个参与者(actor)、团队、系统或阶段,泳道内的节点表示发生在该负责人身上的工作,箭头表示工作的先后顺序以及发生在泳道之间的"交接(handoff)"。
当流程中最重要的信息不仅是"下一步是什么",还包括"这一步由谁拥有"时,就该使用泳道图。典型场景包括:
- 审批流(申请人 / 审核人 / 系统);
- 支持/工单流程(客户 → 支持 → 工程);
- 交付与履约工作流(订单 → 仓储 → 物流);
- 任何需要跨团队、跨系统协作的业务过程。
快速开始:第一个泳道图示例
泳道图以 swimlane-beta 关键字开头,随后可用 subgraph 声明泳道、用 flowchart 风格语法声明节点与连线。下面是一个最基础的客户支持流程:
swimlane-beta LR
subgraph Customer
request[Request service]
receive[Receive update]
end
subgraph Support
triage[Triage request]
answer[Send answer]
end
subgraph Engineering
investigate[Investigate issue]
fix[Prepare fix]
end
request --> triage
triage -->|Known issue| answer
triage -->|Needs code change| investigate
investigate --> fix --> answer
answer --> receive
说明:本页示例使用了 Neo 外观与 Redux 主题渲染;开箱即用时,泳道图使用你配置的默认 look 与 theme,无需额外设置。
从渲染结果可以看出:请求先在 Customer 泳道发起,交接给 Support 泳道做分类,遇到"需要改代码"的分支再交接给 Engineering,最终答案又回到 Customer。泳道本身即承担了"归属"这一维度的信息表达。
核心语法:声明关键字与方向
一个泳道图必须从 swimlane-beta 关键字开始,其后可以(可选地)跟一个方向声明:
swimlane-beta
swimlane-beta LR
支持的方向及含义如下:
| 方向 | 含义 |
|---|---|
TB |
从上到下(Top to bottom) |
TD |
自上而下,与 TB 相同 |
BT |
从下到上(Bottom to top) |
LR |
从左到右(Left to right) |
RL |
从右到左(Right to left) |
若未显式声明方向,默认使用 TB。 从源码角度看,swimlane 图对方向的解析完全复用了 flowchart 的语法能力,因为它本质上是一个"复用 flowchart 解析器、数据库与渲染器,仅替换布局引擎"的图类型(详见下文 实现原理)。
Lanes(泳道):用 subgraph 声明
泳道使用 subgraph ... end 块声明。在泳道图中,顶层的 subgraph 会被渲染为泳道。
swimlane-beta
subgraph Sales
lead[Qualify lead]
quote[Prepare quote]
end
为泳道指定内部 id 与显示标签
当标签包含空格,或希望为样式化提供一个稳定 id 时,可以使用 subgraph id [label] 形式,为泳道同时指定内部 id 和展示标签:
swimlane-beta LR
subgraph sales [Sales team]
lead[Qualify lead]
quote[Prepare quote]
end
subgraph finance [Finance team]
review[Review terms]
approve[Approve quote]
end
lead --> quote --> review --> approve
Nodes(节点):flowchart 风格形状
泳道内部的节点使用与 flowchart 相同的"形状"语法:先写节点 id,再在形状符号内写标签。例如下面覆盖了最常见的几种节点形态(起止、普通任务、分支判断):
swimlane-beta LR
subgraph Intake
start([Start])
task[Do work]
fix[Fix issues]
end
subgraph Review
decision{Ready?}
end
subgraph Complete
done((Done))
end
start --> task --> decision
decision -->|Yes| done
decision -->|No| fix
fix --> task
最常见的节点写法与对应形状、用途归纳如下:
| 语法 | 形状 | 常见用途 |
|---|---|---|
id[Text] |
矩形 | 任务或活动 |
id(Text) |
圆角矩形 | 步骤或事件 |
id([Text]) |
体育场形(两端半圆) | 开始或结束 |
id{Text} |
菱形(决策) | 分支判断问题 |
id((Text)) |
圆形 | 连接点或标记 |
更完整的形状目录(图标、图片、Markdown 字符串、类定义与样式化等),请直接参见 Flowchart 语法。
Edges(连线):支持同泳道与跨泳道
连线同样沿用 flowchart 语法,既可以连接同一泳道内的节点,也可以跨泳道连接(跨泳道连线即"交接"):
swimlane-beta LR
subgraph Buyer
choose[Choose product]
pay[Pay invoice]
end
subgraph Store
reserve[Reserve stock]
ship[Ship product]
end
choose --> reserve
reserve -->|Invoice ready| pay
pay --> ship
常见的连线写法:
| 语法 | 含义 |
|---|---|
A --> B |
带箭头的连线 |
A --- B |
无箭头的连线 |
A -->|Label| B |
带标签的箭头连线 |
A -.-> B |
虚线箭头 |
A ==> B |
粗箭头 |
完整的连线语法(包括多向箭头、最小连线长度等),参见 Flowchart 语法 · Links between nodes。
无障碍访问:accTitle 与 accDescr
与 Mermaid 其他图类型一致,泳道图支持使用 accTitle 与 accDescr 提供无障碍标题与描述,便于屏幕阅读器与辅助技术理解图意:
swimlane-beta LR
accTitle: Support escalation
accDescr: A request starts with the customer, is triaged by support, and may be escalated to engineering.
subgraph Customer
request[Open request]
end
subgraph Support
triage[Triage]
end
subgraph Engineering
resolve[Resolve]
end
request --> triage --> resolve
实现原理:基于 flowchart 的 "layout-variant" 图
理解泳道图最好从源码切入。它是一个相当有代表性的架构示例——没有复制 flowchart 的实现,而是整体复用了 flowchart 的解析器(parser)、数据模型(db)与渲染器(renderer),只替换了默认布局引擎与泳道专用样式。
源码 swimlanesDiagram.ts 中的注释清楚地说明了这一点:swimlane 是"布局变体图(layout-variant diagram)",它刻意调用 flowchart 的公开工厂函数 createFlowDiagram 而非重复整个 flowchart 插件,这是跨图隔离规则的唯一特许例外——依赖仅作用于 flowchart 的导出入口,绝不触碰其内部实现:
// packages/mermaid/src/diagrams/swimlanes/swimlanesDiagram.ts
import { createFlowDiagram } from '../flowchart/flowDiagram.js';
import swimlanesStyles from './styles.js';
export const diagram = createFlowDiagram({ defaultLayout: 'swimlane', styles: swimlanesStyles });
与之配套的检测与懒加载逻辑位于 detector.ts:检测器用正则 /^\s*swimlane-beta\b/ 识别文本是否以 swimlane-beta 开头,然后通过异步 loader 在真正需要渲染时才加载该图插件:
const detector: DiagramDetector = (txt) => /^\s*swimlane-beta\b/.test(txt);
该插件随后注册进 Mermaid 的图编排表(见 diagram-orchestration.ts 中对 swimlanes 的引入与注册),与 flowchart、sequence 等图类型一同参与分发。
在样式层面,styles.ts 复用 flowchart 的完整样式函数,再追加泳道专用规则:因为泳道簇(cluster)形状会自行绘制泳道边界,需要把通用的 .cluster rect 边框抑制掉——具体做法是把其描边颜色与簇背景相匹配,并且是主题自适应的(而非写死某种颜色):
const getStyles = (options: FlowChartStyleOptions): string =>
`${getFlowchartStyles(options)}
.swimlane.cluster rect {
stroke: ${options.clusterBorder} !important;
}
[data-look="neo"].cluster rect {
filter: none;
}
`;
真正产生泳道布局效果的是 defaultLayout: 'swimlane' 所指向的专用布局流水线。在 rendering-util/layout-algorithms/swimlanes 目录下可以看到该布局引擎的完整模块:负责主干流程的 pipeline.ts/layoutCore.ts、方向变换(direction/ 下如 lrTransform.ts 处理 LR/RL 等方向的坐标换算)、泳道内排序(__tests__/laneOrdering.spec.ts)、正交连线路由器(orthogonalRouter/router.ts)等;同时还有大量针对布局质量的端到端用例(如 __tests__/pipeline.lr.e2e.spec.ts、15-border-hugging-lr.ddlt.spec.ts)。此外 swimlanesDiagram.spec.ts 验证了图类型本身的行为,而仓库根目录 e2e/diagrams/swimlanes 下的一组 .mmd 样例则用于快照级视觉回归。
泳道图专项配置(SwimlaneDiagramConfig)
由于复用了 flowchart 渲染器与配置(如 curve、htmlLabels、间距等共享选项),泳道图的大部分外观由 flowchart 配置控制;只有布局管线专用的"旋钮"集中在 SwimlaneDiagramConfig 配置块中。其类型定义见 config.type.ts:
| 配置项 | 类型 | 含义 |
|---|---|---|
lineHops |
boolean | 'arc' | 'gap' |
把交叉边渲染成小圆弧("hops")或可见间隙,减少重叠边的阅读困难;设为 false 可关闭。渲染为曲线的边会被跳过,以免破坏几何形状 |
ignoreCrossLaneEdges |
boolean |
在做泳道分层(layer assignment)时忽略跨越泳道边界的边。对于含大量跨泳道连线的图,可改善层级质量 |
optimizeRanksByCrossings |
boolean |
为泳道布局启用一次"感知交叉的等级优化(crossing-aware rank optimization)"扫描 |
automaticLaneOrdering |
boolean |
用确定性加权线性排列启发式自动重排顶层泳道。默认关闭——因为源码中泳道的书写顺序本身可能携带语义 |
其中尤其值得注意 automaticLaneOrdering:源码注释明确说明它默认不启用,原因是"源码泳道顺序可能承载语义"——即在手工编排的泳道图中,泳道自左(或自上)而下的次序常常对应责任方出场顺序。若交给算法重排,虽然可能减少交叉,却可能改变叙述顺序。
配置方式与其他图类型一致,可通过 initialize 或在文本中通过 %%{ init: ... }%% 指令下发。例如:
mermaid.initialize({
startOnLoad: true,
swimlane: {
lineHops: true,
automaticLaneOrdering: false,
optimizeRanksByCrossings: true,
},
});
最佳实践
让每条泳道只表达一种"归属"
泳道应当回答"这一步由谁负责?"。除非"区分团队/阶段/状态"正是这张图的表达目的,否则不要在同一张图里混用团队、阶段与状态三种维度。
swimlane-beta LR
subgraph Customer
submit[Submit order]
confirm[Confirm delivery]
end
subgraph Store
check[Check order]
pack[Pack items]
end
subgraph Carrier
collect[Collect package]
deliver[Deliver package]
end
submit --> check --> pack --> collect --> deliver --> confirm
为跨泳道交接连线加标签
跨泳道箭头意味着责任方的变更。当交接依赖某份文档、一次决策、一条消息或某个条件时,请为这条箭头补上标签,读者才能知道"为什么在这里换人":
swimlane-beta LR
subgraph Applicant
apply[Submit application]
sign[Sign agreement]
end
subgraph Reviewer
screen[Screen application]
decide{Approved?}
end
subgraph System
create[Create account]
notify[Send welcome email]
end
apply -->|Application received| screen
screen --> decide
decide -->|Approved| create --> notify --> sign
decide -->|Needs changes| apply
长流程要"可一眼读通"
当泳道或交接数量多到一屏放不下时,把一个大的过程拆成多张图。一张好用的泳道图通常应该不需要读者反复追线两遍。
swimlane-beta TB
subgraph Intake
collect[Collect request]
validate[Validate details]
end
subgraph Review
review[Review request]
decide{Ready?}
end
subgraph Delivery
schedule[Schedule work]
complete[Complete work]
end
collect --> validate --> review --> decide
decide -->|Yes| schedule --> complete
decide -->|No| collect
使用稳定的 id
为节点和泳道使用简短而有意义的 id。标签可以在不破坏连线、样式或后续引用的前提下随意修改,因此把"引用稳定性"寄托在 id 上。注意泳道也支持与 flowchart 相同的类与样式语句:
swimlane-beta LR
subgraph ops [Operations]
intake[Receive request]
plan[Plan work]
end
subgraph legal [Legal]
review[Review contract]
end
intake --> plan --> review
classDef attention fill:#fff2cc,stroke:#d6a500,color:#111;
class review attention;
把决策节点放在"做决定的人"所在泳道
决策发生在哪一方,就把菱形节点放在哪一方,然后让不同分支结果路由到实际执行动作的泳道:
swimlane-beta LR
subgraph Support
classify{Can support solve it?}
respond[Respond to customer]
end
subgraph Product
prioritize[Prioritize fix]
end
subgraph Engineering
implement[Implement fix]
end
classify -->|Yes| respond
classify -->|No| prioritize --> implement --> respond
何时改用其他图类型
泳道图并非万能,官方文档给出了清晰的选型边界:
- 当归属不重要、只需要表达顺序或分支时,改用普通的 flowchart;
- 当重点在于参与者之间随时间流动的消息时,改用 sequence 顺序图;
- 当重点是某一个对象如何随事件改变状态时,改用 state 状态图。
一句话概括:泳道图的价值在于同时呈现"流程顺序 + 责任归属 + 交接条件"三个维度;如果你只关心其中一维,其他图类型往往更简洁。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00