欢迎使用 FlowZap,快速、清晰、掌控的绘图应用。

如何编写和编辑 FlowZap 代码(无需技术技能!)

FlowZap 代码是可视化背后的引擎——一种精简的文本式接口,用来弥合便签式想法与专业制图之间的鸿沟。不同于复杂的编程语言,它采用自然直观的语法,让你像写待办清单一样轻松地描述流程、泳道与连接。作为单一事实来源,它同时驱动工作流与序列两种视图,让你无需重画任何元素即可瞬间切换视角。只需在编辑器中定义逻辑,点击"更新",FlowZap 就会在毫秒内把原始文本转化为精致、可上台演示的体系结构。

无论您是人类开发者还是 AI 编码助手,本指南都将帮助您生成有效的 FlowZap 代码,可保存为 `.fz` 文件并由 FlowZap.xyz 渲染。

FlowZap Code Editor UI

核心输出规则

  • 始终输出原始 FlowZap 代码,不带 Markdown 围栏、不带解释、不带任何周围文本。
  • 不要添加"这是您的代码"之类的注释或 ``` 围栏;直接返回代码主体。
  • 仅使用 UTF-8 纯文本;不使用表情符号,不使用不可打印字符。

FlowZap 图表的高层结构

  • FlowZap 图表是由泳道、节点、边和可选循环片段组成的纯文本描述。
  • 每个泳道将一个参与者或系统的相关步骤分组(如 UserApplicationServer)。
  • 节点定义步骤或决策;边定义节点之间的方向流。
  • 循环描述重复行为(如重试),可以涉及跨泳道的节点。

全局约束(非常重要)

  • 节点 ID 必须遵循 n1n2n3、… 的模式,并且在单个图表的所有泳道中必须全局唯一。
  • 节点编号必须连续且无间隔(例如 n1n2n3,而不是 n1n3n5)。始终使用从 1 开始的连续整数。
  • 节点只允许四种形状:circlerectanglediamondtaskbox
  • 节点属性使用 键:"值" 带冒号,而边标签使用 label="值" 带等号在方括号内。
  • 不要生成任何 Mermaid、PlantUML 或其他图表语法,如 graph TDsequenceDiagramparticipant-->
  • 不要发明新的属性键;仅使用 labelownerdescriptionsystem 和此处描述的类似英文键。

泳道(参与者/泳道)

每个泳道以泳道标识符开始,后跟左大括号和单个显示标签注释。

User { # User
...
}

泳道 ID 是简单的标识符,如 UserApplicationServerflowprocessops。每个泳道只允许一个注释,紧跟在左大括号后,使用 # 显示标签。不要在代码的其他地方放置注释。

Do:

  • User { # User
  • flow { # Flow

Don't:

  • // User 或左大括号外的注释
  • 同一泳道块中有多个 # 注释

节点(步骤、决策、任务)

每个节点在单独一行定义,格式为:nX: shape label:"文本" 加可选属性。

n1: circle label:"开始"
n2: rectangle label:"输入用户名和密码"
n3: diamond label:"格式有效?"
n4: taskbox owner:"Alice" description:"部署" system:"CI"

允许的形状:circle(开始/结束)、rectangle(流程/动作)、diamond(决策)、taskbox(带 owner/system 的分配任务)。在节点 ID 和形状之间使用冒号(:),所有节点属性也使用冒号(如 label:"...")。节点标签必须用双引号括起来。保持节点标签简洁但具有描述性,通常少于 50 个字符。

Do:

  • n1: circle label:"开始"
  • n3: diamond label:"是否有效?"
  • n1: taskbox owner:"Alice" description:"部署" system:"CI"

Don't:

  • n1: circle label="开始" (错误的分隔符)
  • n3 diamond "是否有效?" (缺少冒号)
  • 使用未知属性如 priority:"high"

边(节点之间的连接)

边始终将一个节点的 .handle(direction) 连接到另一个节点的 .handle(direction)

n1.handle(right) -> n2.handle(left)
n2.handle(bottom) -> Application.n3.handle(top) [label="发送"]

边的基本格式:sourceNode.handle(direction) -> targetNode.handle(direction) [label="文本"]。方向必须是:leftrighttopbottom 之一。对于跨泳道边,在目标前加上泳道名称,如 Application.n6.handle(top)。边标签使用等号加方括号,如 [label="是"],绝不使用冒号:[label:"是"]。边标签是可选的。

Do:

  • n1.handle(right) -> n2.handle(left) [label="前进"]
  • n3.handle(bottom) -> laneB.n5.handle(top)
  • n2.handle(bottom) -> Application.n6.handle(top) [label="发送"]

Don't:

  • n1.handle(right) -> n2.handle(left) [label:"前进"] (错误的等号)
  • n3.handle(bottom) -> n5 (跨泳道边缺少泳道)
  • n2 -> n6 [label="发送"] (没有句柄)

跨泳道连接

从一个泳道的节点连接到另一个泳道的节点时,在目标节点前加上泳道 ID。

n3.handle(bottom) -> Application.n6.handle(top) [label="发送凭据"]
n8.handle(top) -> User.n2.handle(bottom) [label="否 - 错误"]

将边定义保留在泳道的大括号内。永远不要省略跨泳道目标的泳道前缀;始终写 泳道Id.nX

序列图最佳实践

FlowZap 代码同时渲染为工作流视图和序列视图。序列视图按边定义顺序从上到下绘制消息。在编写多泳道代码时,请遵循以下规则以获得清晰、合乎逻辑的序列图。

  • 请求-响应配对 — 每个跨泳道请求边都必须有对应的返回边。如果泳道 A 向泳道 B 发送消息,泳道 B 最终必须发送响应回来。缺少响应会创建不完整、误导性的图表。
  • 边的时间顺序 — 按事件发生的时间顺序定义边。序列图根据边的定义顺序(而非节点 ID)从上到下渲染消息。乱序的边会产生令人困惑的箭头序列。
  • 无孤立节点 — 每个节点必须参与至少一条边(作为源或目标)。没有任何边的节点在序列图中显示为断开的、无意义的步骤。
  • 分离异步流 — 如果图表包含独立的流(例如主请求路径和后台监控路径),请先定义所有主流程的边,然后定义异步/后台的边。永远不要交错不相关的流。

正确做法:请求与匹配的响应

Client { # 客户端
n1: rectangle label:"发送请求"
n2: rectangle label:"接收响应"
n1.handle(bottom) -> Server.n3.handle(top) [label="HTTP GET"]
}
Server { # 服务器
n3: rectangle label:"处理请求"
n4: rectangle label:"返回数据"
n3.handle(right) -> n4.handle(left)
n4.handle(top) -> Client.n2.handle(bottom) [label="200 OK"]
}

错误做法:缺少响应,孤立节点

Client { # 客户端
n1: rectangle label:"发送请求"
n2: rectangle label:"接收响应"
n1.handle(bottom) -> Server.n3.handle(top) [label="HTTP GET"]
}
Server { # 服务器
n3: rectangle label:"处理请求"
n4: rectangle label:"返回数据"
n3.handle(right) -> n4.handle(left)
}

问题:n2 是孤立的(没有边),并且没有从服务器到客户端的返回边。序列图显示请求发出但从未返回。

循环(LOOP 片段)

使用 loop 关键字描述重复行为,如重试。

loop [重试直到格式有效] n2 n3 n7 n8
loop [最多重试 3 次] n2 n3 n4

基本格式:loop [条件] n1 n2 n3 ...,其中条件是纯文本,后面的标记是节点 ID。条件应简短且具有描述性。按执行顺序列出循环中涉及的节点;它们可以在一个或多个泳道中。不要嵌套循环;保持它们扁平并在相关节点之后定义。

最小完整模板

从模糊提示开始时使用这些骨架;根据请求的流程调整标签和边。

Single-lane minimal flow

process { # 流程
n1: circle label:"开始"
n2: rectangle label:"步骤"
n3: circle label:"结束"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
}

Two-lane user–app interaction

user { # 用户
n1: circle label:"开始"
n2: rectangle label:"提交"
n1.handle(right) -> n2.handle(left)
n2.handle(bottom) -> app.n3.handle(top) [label="发送"]
}
app { # 应用
n3: rectangle label:"处理"
n4: circle label:"完成"
n3.handle(right) -> n4.handle(left)
}

Decision branch

flow { # 流程
n1: rectangle label:"检查"
n2: diamond label:"OK?"
n3: rectangle label:"修复"
n4: rectangle label:"继续"
n1.handle(right) -> n2.handle(left)
n2.handle(bottom) -> n3.handle(top) [label="否"]
n2.handle(right) -> n4.handle(left) [label="是"]
}

Simple loop

flow { # 流程
n1: rectangle label:"验证"
n2: diamond label:"有效?"
n1.handle(right) -> n2.handle(left)
loop [重试直到有效] n1 n2
}

Taskbox example

ops { # 运维
n1: taskbox owner:"Alice" description:"部署" system:"CI"
}

完整示例:多泳道认证流程

将此模式用作典型"认证"或"登录"流程的参考。

User { # 用户
n1: circle label:"开始"
n2: rectangle label:"输入用户名和密码"
n3: rectangle label:"提交表单"
n4: rectangle label:"收到确认"
n5: circle label:"访问已授权"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
n3.handle(bottom) -> Application.n6.handle(top) [label="发送凭据"]
n4.handle(right) -> n5.handle(left)
loop [重试直到格式有效] n2 n3 n7 n8
}
Application { # 应用
n6: rectangle label:"接收请求"
n7: rectangle label:"验证格式"
n8: diamond label:"格式有效?"
n9: rectangle label:"转发到服务器"
n14: rectangle label:"转发确认给客户端"
n6.handle(right) -> n7.handle(left)
n7.handle(right) -> n8.handle(left)
n8.handle(right) -> n9.handle(left) [label="是"]
n9.handle(bottom) -> Server.n10.handle(top) [label="认证"]
n8.handle(top) -> User.n2.handle(bottom) [label="否 - 错误"]
n14.handle(top) -> User.n4.handle(bottom) [label="成功"]
}
Server { # 服务器
n10: rectangle label:"检查数据库"
n11: diamond label:"凭据有效?"
n12: rectangle label:"生成会话令牌"
n13: rectangle label:"返回错误"
n10.handle(right) -> n11.handle(left)
n11.handle(right) -> n12.handle(left) [label="是"]
n11.handle(bottom) -> n13.handle(bottom) [label="否"]
n12.handle(top) -> Application.n14.handle(bottom) [label="令牌"]
n13.handle(top) -> Application.n6.handle(bottom) [label="错误 401"]
}

常见错误避免

  • 不要将泳道注释放在单独的行上。# 显示标签 必须与左大括号在同一行泳道名 { # 标签,而不是 泳道名 { 后跟下一行的 # 标签
  • 不要在节点上使用 label="文本";节点标签必须是 label:"文本"
  • 不要在边的方括号内使用 label:"文本";边必须是 [label="文本"]
  • 不要在跨泳道边上省略泳道前缀(如跨泳道时 n3 -> n5 是无效的)。
  • 不要引入其他图表语法(Mermaid、UML、JSON、YAML、XML)。
  • 不要在图表中重复使用节点 ID(n1n2、…);每个 ID 必须全局唯一。
  • 不要跳过节点编号。节点 ID 必须连续且无间隔(例如 n1n2n3,而不是 n1n3n5)。如果有 14 个节点,必须从 n1n14 连续编号。
  • 不要在每个泳道左大括号后的 # 显示标签 之外添加额外注释。
  • 不要在泳道的大括号之外使用循环。循环只能出现在泳道的大括号({...})内部。

LLM 提示技巧(面向人类开发者)

  • 始终包含类似这样的指令:参考 docs/flowzap-code-guidelines.md 并仅输出此流程的有效 FlowZap 代码。
  • 提供流程的简短、清晰描述:参与者、关键步骤、决策和循环(如带重试的登录、带支付网关的结账)。
  • 如果 LLM 输出包含 Markdown、解释或无效语法,重新提示:删除所有 Markdown 和解释;仅按照指南输出 FlowZap 代码。
  • 对于更新,粘贴现有的 FlowZap 代码并说:就地修改此代码:添加 [新步骤/分支/循环],同时保持 ID 唯一和语法有效。

AI 代理的最终提醒

您的任务是生成遵循上述所有语法和结构规则的有效 FlowZap 代码文本,以便它可以保存为 .fz 文件并由 FlowZap 渲染,无需手动修复。

下载 FlowZap 代码 LLM 指南 (.md)(英文指南)

更多示例在这里

在 Github 上查看更多示例