飞书画板流程图 DSL 实战指南Dagre 拓扑、复合节点与语义化配色全解析【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli本篇指南聚焦 lark-whiteboard 技能体系中流程图Flowchart场景的完整创作范式从「必须走 DSL 路径、不再使用 Mermaid」的硬性约束到 Dagre 拓扑布局、不透明节点/透明子图两种嵌套模式、语义化配色、edges边定义与陷阱防范。读完你可以在飞书画板中直接产出带条件判断、分支回路、系统架构拓扑的高质量业务流程图并理解其底层 DSL 布局引擎Flex/Yoga Dagre的工作原理。流程图场景定位与适用边界根据 skills/lark-whiteboard/scenes/flowchart.md流程图适用于各种业务流转图决策树审批流时序控制逻辑带条件判断的链路系统架构拓扑文档中通用的字段语义见 elements/schema.md通用布局原则见 elements/layout.md流程图场景文件只负责描述选型边界与范式——即什么情况下用哪种布局、节点如何组织、连线如何声明。硬性约束流程图必须走 DSL 路径[!IMPORTANT]流程图必须走 DSL 路径不再使用 Mermaid复杂分支、判断、回路、跳级关系优先使用layout: dagre计算拓扑如果只是规整的单线流水线且卡片强对齐比自动拓扑更重要也可以使用 Flex 顶层connector组合实现。这一点与 routes/dsl.md 中「DSL 路径」的创作工作流完全一致流程图属于必须产出完整 DSL JSON而非 Mermaid 源码的场景类型。整个 lark-whiteboard 技能本身也以 DSL 为核心语法——从 SKILL.md 可以看到只有用户已提供Mermaid/PlantUML/SVG 代码或明确指定格式时才走对应update --input_format路径其余新建复杂图表一律进入 DSL 创作工作流。美学规范摒弃简陋节点推崇全卡片化流程图不是把几个方块用线连起来就算完成。文档给出了四条核心美学要求摒弃简陋节点推崇全卡片化核心业务节点不要只用一个纯文本rect。应优先采用 Flex 组合卡片——例如在verticalframe 内上下组合【Emoji 标题项】和【补充说明项】让节点信息结构化、层级分明。语义化色彩编排节点底色严禁随机分配必须按状态语义映射常规链路浅蓝/浅紫核心风控/检查预警黄成功通过生命绿失败熔断危险红边框颜色可同色系加深以凸显卡片边缘统一判定逻辑条件分支必须使用diamond菱形节点并且严禁漏掉layoutOptions.edges边定义里的第三个标签参数必须清晰写明「是/否」「通过/拒绝」。形状多样化合理搭配不同形状表达语义ellipse外部实体/起终点diamond判断路由rect业务处理节点cylinder持久化存储关于语义化配色elements/style.md 给出了更系统的经典色板规则外层大分区用浅色填充背景如#F0F4FC浅蓝、#EAE2FE浅紫内层具体节点用白色填充 分组色边框borderWidth2连线统一用灰色#BBBFC4不抢节点注意力。流程图的上色范式是「起止节点一种颜色、判断节点一种颜色、步骤节点白色」——这与本文档的语义化色彩要求完全对应。Layout 选型四种模式的适用边界模式适用条件核心配置主体用 Dagre有判断、分支、回路、回退、跳级关系的标准流程图主体 frame 设定layout: dagre按需配置rankdir: TB或rankdir: LR局部复合节点流程中的某一步本身是一个小型 UI 组合体外层仍用dagre复合步骤内部改用layout: vertical/horizontal。此类节点为不透明节点外层连线只能连到外壳透明子图需按业务区域分组且连线穿越区域边界子容器声明layout: dagrelayoutOptions: { isCluster: true }成为透明子图。内部节点直接参与外层拓扑运算规整流水线基本是单线 A → B → C → D且卡片对齐要求极高主体可用 Flex 排版连线改用顶层connector不要为了「自动」而硬上 Dagre从底层实现看layout属性在 DSL 中只支持四种取值horizontal、vertical、none、dagre见 elements/schema.md 中 Frame 节点定义。dagre是专属拓扑连线引擎Frame 布局本身基于 Yoga 引擎、行为等同 Flexbox。文档 elements/layout.md 进一步给出了 Dagre 版式统一原则Dagre 解决的是拓扑关系不是自动把画布铺满选用 Dagre 前先看三件事——最长链路方向、分支是否对称、是否有长回边/重试回路哪一项失衡都会把包围盒撑歪。核心属性速查rankdir布局方向TB上下或LR左右。强烈推荐优先使用LR充分利用宽屏横向空间。schema 层还支持BT与RL即四种取值TB | BT | LR | RL见 elements/schema.md。edges边定义与反向连接在根 Dagre 的layoutOptions.edges中按[fromId, toId, 标签]声明。支持反向连接实现闭环。所有 edges 统一写在最外层根 Dagre不要写在 cluster 内部。注意 schema 对 edges 的定义是Array[string, string] | [string, string, string]即元组可以只有两元素无标签也可以带第三个标签字符串引擎会根据 edges 自动排版子节点并生成贝塞尔曲线连线。ranksep与边文本若边上标注了说明文字必须根据字数调大间距ranksep max(60, 字数 × 16)自适应尺寸dagre 容器必须设定width: fit-content和height: fit-content。这是因为 Dagre 的尺寸由拓扑计算得出、无法提前预知——elements/layout.md 明确警告「不要给 Dagre 套固定宽高的外框」且 Dagre 自身不支持fill-container宽高对其父容器而言它是自适应打包裹的黑盒。clusterTitle与clusterTitleColor透明子图可通过clusterTitle声明悬浮标题自动吸附左上角、加粗 14px搭配clusterTitleColor指定标题颜色HEX 格式如#8B5CF6。两种嵌套模式不透明节点与透明子图这是流程图尤其是系统架构拓扑中最容易混淆、也最关键的机制。schema 层给出三条 Dagre 嵌套排版规则见 elements/schema.md不透明节点Opaque NodeDagre 内的子容器无论内部 layout 是 flex、absolute 还是 dagre只要未声明isCluster: true对外层 Dagre 就是具有确定宽高的不透明原子节点。外层连线无法寻址其内部子节点。连线兜底重定向Edge Redirect Fallback当edges引用了某不透明节点内部的子节点 ID 时引擎自动将该连线端点重定向至其最近的不透明祖先节点。不报错不产生悬空连线。透明子图Compound Cluster子容器同时声明layout: dagre与layoutOptions: { isCluster: true }时成为外层 Dagre 的复合子图。其内部子节点直接参与外层拓扑运算连线可穿越子图边界。子图自身不执行独立排版尺寸由外层 Dagre 根据内部节点包围盒自动撑开。不透明节点适合封装复杂的组合卡片——如带图标、版本号、多行描述的业务模块。外层连线无法穿透只能连到外壳 ID。透明子图适合划分网络区域、功能层级、命名空间等边界容器。推荐搭配borderDash: dashed虚线边框 淡色背景。schema 中给出了 isCluster 的最小用法{ type: frame, id: cluster_a, layout: dagre, layoutOptions: { isCluster: true }, fillColor: #F0FDF4, borderColor: #86EFAC, borderWidth: 2, borderDash: dashed, borderRadius: 16, children: [ { type: text, text: 区域标题, fontSize: 11, textColor: #15803D }, { type: rect, id: node_inside, width: 120, height: 40, text: 内部节点 } ] }注意edges必须写在最外层的根 Dagre的layoutOptions中不要写在 cluster 内部。骨架示例混合架构拓扑推荐范本以下完整示例来自 skills/lark-whiteboard/scenes/flowchart.md同时展示了透明子图Kubernetes Zone连线可穿透和不透明复合节点DB 集群、AI 引擎连线只能连外壳的标准写法以及多种形状ellipse / diamond / rect / cylinder和语义化配色规范{ version: 2, nodes: [ { type: frame, id: root, x: 20, y: 20, layout: dagre, width: fit-content, height: fit-content, padding: 60, fillColor: #F8FAFC, borderColor: #CBD5E1, borderWidth: 1, borderRadius: 16, layoutOptions: { rankdir: LR, nodesep: 60, ranksep: 120, edges: [ [user, k8s_ingress, HTTPS request], [k8s_ingress, web_pod, Route UI], [k8s_ingress, api_pod, Route API], [web_pod, api_pod, Internal REST], [api_pod, db_cluster, SQL Query], [api_pod, ai_service, gRPC Stream] ] }, children: [ { type: ellipse, id: user, text: Global Users, width: 110, height: 60, fillColor: #E2E8F0, borderColor: #64748B, borderWidth: 1, fontSize: 14, textColor: #334155 }, { type: frame, id: zone_k8s, layout: dagre, layoutOptions: { isCluster: true, clusterTitle: ☸️ Kubernetes Zone (isCluster), clusterTitleColor: #2563EB }, fillColor: #EFF6FF, borderColor: #60A5FA, borderWidth: 2, borderDash: dashed, borderRadius: 24, children: [ { type: diamond, id: k8s_ingress, text: Nginx Ingress, width: 130, height: 70, fillColor: #DBEAFE, borderColor: #3B82F6, borderWidth: 2, textColor: #1E40AF }, { type: rect, id: web_pod, text: Next.js SSR Pod, width: 140, height: 48, fillColor: #BFDBFE, borderColor: #2563EB, borderWidth: 2, borderRadius: 8, textColor: #1E3A8A }, { type: rect, id: api_pod, text: Go Lang API Pod, width: 140, height: 48, fillColor: #BFDBFE, borderColor: #2563EB, borderWidth: 2, borderRadius: 8, textColor: #1E3A8A } ] }, { type: frame, id: db_cluster, layout: vertical, gap: 16, padding: [20, 24], alignItems: center, fillColor: #F0FDF4, borderColor: #22C55E, borderWidth: 2, borderRadius: 16, children: [ { type: text, id: db_title, text: ️ Highly Available DB (不透明), fontSize: 14, textColor: #14532D }, { type: frame, id: db_row, layout: horizontal, gap: 20, children: [ { type: cylinder, id: db_master, text: Master, width: 80, height: 50, fillColor: #DCFCE7, borderColor: #16A34A, borderWidth: 1, textColor: #166534 }, { type: cylinder, id: db_replica, text: Replica, width: 80, height: 50, fillColor: #DCFCE7, borderColor: #16A34A, borderWidth: 1, textColor: #166534 } ] } ] }, { type: frame, id: ai_service, layout: vertical, gap: 10, padding: [16, 20], alignItems: center, fillColor: #FAF5FF, borderColor: #A855F7, borderWidth: 2, borderRadius: 12, children: [ { type: text, id: ai_title, text: Multi-Modal Engine (不透明), fontSize: 14, textColor: #6B21A8 }, { type: rect, id: ai_version, text: v4.2.1-beta, width: 90, height: 22, fillColor: #E9D5FF, borderColor: #C084FC, borderWidth: 1, borderRadius: 4, fontSize: 11, textColor: #581C87 }, { type: text, id: ai_desc, text: Includes Vector Store\n Transformer Blocks, fontSize: 12, textColor: #7E22CE, textAlign: center } ] } ] } ] }范本要点zone_k8s是透明子图isCluster: trueclusterTitle外部连线穿越虚线边界直达k8s_ingress、web_pod、api_pod。db_cluster和ai_service是不透明节点layout: vertical内部用 Flex 组合了多行结构化信息对外层 Dagre 是固定宽高的原子。连线只能连到外壳 ID。所有edges统一写在最外层根 Dagre 的layoutOptions中。范本中用到了ellipse外部实体、diamond路由判断、rect业务节点、cylinder数据库存储四种形状。范本中的两个实现细节cylinder约束从 elements/schema.md 可知 cylinder 弧度固定 16px、不随宽度缩放宽度过大会变成扁椭圆禁止width: fill-container必须用固定宽度 height: fit-content宽度通常取 120-200px。Shape 内边距TEXT_INSETrect / ellipse / diamond / triangle 各边有 12px 强制内边距cylinder 垂直方向 42px需要手算固定尺寸时用实际文字宽/高 对应 inset例如 rect 内 14px 字号两行文字高约 32px则height 32 24 56px。陷阱与常见报错防范文档最后给出了五条高频踩坑点并结合底层实现补充说明误用 Mermaid只要用户没有带mermaid具体语法代码哪怕描述明确是「流程图」也强制使用 DSL 框架下的 Dagre 模式。重复画线dagre里的所有子节点关系通过edges定义引擎会自动生成连线。绝对不要再去外层用connector节点重复连一次会产生双线。对照 elements/connectors.md 可知connector 是顶层 nodes 数组中的显式连线元素只应用于 Flex/绝对定位场景而 Dagre 内部的拓扑连线完全由layoutOptions.edges驱动。穿透黑盒普通子容器是不透明节点外部连线无法直接寻址其内部子节点引擎会自动重定向至外壳。若需穿透必须声明layout: dagre与layoutOptions: { isCluster: true }。id缺失只要是在edges里出现的标识符children里一定能找到同名id的节点对应拼写必须完全一致否则连线悬空。宽度灾难Dagre 内容器禁止子框使用fill-container因为 dagre 父容器本身是被内容撑开的自适应黑盒。同理elements/layout.md 还提醒fill-container死锁陷阱——使用fill-container时祖先链中必须有固定宽度否则与fit-content形成死锁、尺寸退化为 0。从 JSON 到画板渲染与写入流程流程图 DSL 产物最终通过 lark-whiteboard 的创作工作流落地详见 references/lark-whiteboard-workflow.mdStep 1 获取 board_token用户直接给wbcnXXX白板 token 则直接使用文档 URL 可用lark-cli docs fetch --doc URL --as user从返回的whiteboard tokenxxx/提取需要新建画板时用lark-cli docs update追加whiteboard typeblank/whiteboard并从响应的data.new_blocks[0].block_token取得。Step 2 渲染 审查routes/dsl.md# 渲染 PNG 仅用于预览验证不是最终产物 npx -y larksuite/whiteboard-cli^0.2.13 -i diagram.json -o diagram.png渲染前需自查不同分组用了不同颜色且同组样式一致外层浅色背景、内层白色节点所有节点有边框连线用灰色不用彩色frame 都写了 layout 且 gap/padding 显式设置含文字节点 height 用 fit-contentStep 3 写入画板用 whiteboard-cli 将 diagram.json 转换为 OpenAPI 格式并 pipe 给updatenpx -y larksuite/whiteboard-cli^0.2.13 -i diagram.json --to openapi --format json \ | lark-cli whiteboard update --whiteboard-token board_token \ --source - --input_format raw --idempotent-token 时间戳标识 --as user产物目录统一为./diagrams/YYYY-MM-DDTHHMMSS/其中diagram.json是 DSL 源文件、diagram.png是渲染结果。整个流程走完即可把流程图交付到飞书画板向用户报告 board_token 写入成功。总结流程图是 lark-whiteboard 技能体系中信息密度最高、最容易踩坑的场景之一。核心要点可归纳为四句话路径选型有判断/分支/回路的标准流程图必须走 DSL 的 Dagre 路径不要用 Mermaid单线规整流水线才考虑 Flex 顶层 connector。节点形态用 Flex 组合卡片替代纯文本 rect用diamond表达判定并写清边标签按状态语义化配色浅蓝常规 / 预警黄 / 生命绿 / 危险红。嵌套机制默认子容器是不透明节点连线只能连外壳需要连线穿越时声明layout: dagrelayoutOptions: { isCluster: true }成为透明子图所有 edges 统一写在最外层根 Dagre。尺寸纪律dagre 容器必须fit-content子节点禁止fill-container边带文字时ranksep max(60, 字数 × 16)优先rankdir: LR利用宽屏。掌握这四点再配合 elements/schema.md、elements/layout.md、elements/connectors.md 与 elements/style.md 四份核心参考即可在飞书画板中稳定产出结构清晰、语义准确、可直接交付的业务流程图与系统架构拓扑图。【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
