跳到正文

这是开发版文档,跟随主分支更新,可能包含尚未发布的功能。

流程编辑器 ​

@dou-ui/flow 提供流程编辑器 DouFlowEditor:在一块可以平移、缩放的画布上摆放节点,节点之间用连线连接。适合编辑 AI 工作流、数据处理流程、自动化规则这类“节点 + 端口 + 连线”的图。

编辑器只负责编辑和展示,不负责运行流程。节点的运行状态由你写进数据,编辑器负责画出来。完整的例子见区块 AI 工作流。

只需要展示、不需要编辑时,用 dou-ui 里的 NodeGraph 就够了,它会自动排好节点的位置。

安装 ​

流程编辑器是单独的包,需要和 dou-ui 一起使用:

sh
bun add dou-ui @dou-ui/flow

引入样式,再注册组件:

ts
import 'dou-ui/style.css'
import '@dou-ui/flow/style.css'
import { DouFlowEditor } from '@dou-ui/flow'

app.use(DouFlowEditor)

也可以只在用到的组件里 import { DouFlowEditor } from '@dou-ui/flow'。

基础用法 ​

v-model 绑定一份包含节点和连线的数据,格式见文档数据。fitView 让画布在节点测量完成后缩放到能看到全部节点;为了字还看得清,最多缩小到 fitMinZoom(默认 50%),再放不下时从左上角开始显示,可以平移查看。

收到提问
检索笔记

在读书笔记里查找相关段落

问题笔记片段
生成回答
问题回答
参考资料没有把握
发送回复
请戴兜确认
  • 拖动节点移动它。拖动时会和附近的节点对齐(出现参考线),连着的端口会吸附到同一高度,让连线变成直线;没有可对齐的对象时吸附到 8px 网格。按住 Alt 拖动可以暂时关闭吸附。
  • 拖动画布空白处平移,滚轮也可以平移,Shift + 滚轮横向平移。Ctrl / ⌘ + 滚轮或触控板捏合缩放。
  • 平移最远到节点刚好移出视野,留出一屏空白画布,不会离节点越来越远。通过 v-model:viewport 设置的位置不受这个限制。
  • 点击选中节点或连线,Shift 点击加选。按住 Shift 在空白处拖动可以框选。
  • Delete 删除选中的节点和连线,删除节点时连在它上面的连线一起删除。
  • Ctrl / ⌘ + Z 撤销,Ctrl / ⌘ + Shift + Z 重做。一次拖动、连续按方向键都只算一步。

连线 ​

  • 从输出端口拖出连线,松开在输入端口上完成连接。靠近端口时会自动吸附,松开在节点的任意位置也会连到它最近的可用端口。
  • 拖动时能连的端口会高亮,不能连的变淡;指针停在不能连的端口上时,端口和连线变红,松开后读屏会说明原因。哪些端口能连由端口类型与连接规则决定,不设置时输出可以连到任何输入。
  • 输入端口默认只接一条线,连到已有连线的输入时会替换原来的连线。
  • 从已有连线的输入端口拖动,可以把这条线改接到别的端口;拖到空白处松开会删除它。
  • 新连线拖到空白处松开时触发 connectToCanvas,可以在这里弹出节点列表,创建节点后再连上。
  • 选中一个节点后按 C 用键盘连线:方向键在能连的端口之间切换,Tab 换一个起点端口,Enter 确认,Esc 取消。

复制和粘贴 ​

Ctrl / ⌘ + C 复制选中的节点和它们之间的连线,Ctrl / ⌘ + V 粘贴到指针所在的位置(指针不在画布上时粘贴在原位置旁边),Ctrl / ⌘ + X 剪切,Ctrl / ⌘ + D 复制一份。

复制的内容以 JSON 写进系统剪贴板,所以可以粘贴到另一个标签页的编辑器里,也可以贴到文本框里查看。

触屏 ​

  • 单指拖动空白处平移,双指捏合缩放。
  • 单指拖动节点移动它。
  • 长按空白处后拖动框选,长按节点把它加入选择。
  • 查找没有手势,需要时自己放一个按钮调用 openSearch(),见查找节点。

键盘 ​

按键作用
Tab / Shift + Tab沿连线的方向在节点之间切换并选中它,同一层的节点从左到右
方向键移动选中的节点一格(grid),加 Shift 移动四格;没有选中节点时平移画布
Alt + 方向键调整选中分组的大小,见分组
Delete / Backspace删除选中的节点和连线
C从选中的节点开始连线
E / Shift + E在选中节点的连线之间切换,见用键盘选中连线
Enter / F2编辑选中连线的标签
Esc拖动中按下时取消这次拖动;查找面板开着时关闭它;否则清除选择
Ctrl / ⌘ + A选中全部节点
Ctrl / ⌘ + C / X / V / D复制、剪切、粘贴、复制一份
Ctrl / ⌘ + G把选中的节点放进分组,加 Shift 取消分组或移出分组,见分组
Ctrl / ⌘ + = / - / 0放大、缩小、恢复 100%
Ctrl / ⌘ + F按名字查找节点,见查找节点
F3 / Shift + F3下一个、上一个查找结果
按住空格拖动平移画布

查找节点 ​

节点多的时候,按 Ctrl / ⌘ + F 在画布右上角打开查找框,按节点显示的名字查找(白板里是形状和便签上的文字)。右上角已有工具栏、控制条之类的面板时,查找框排在它们下面。找到的节点套上一圈底色,当前这一个会被选中并移到画布中央,缩放不变;Enter / Shift + Enter 或 F3 / Shift + F3 在结果之间按阅读顺序前后移动,Esc 关闭。流程图只查找,没有替换。

其他编辑器的下一个结果还可以用 Ctrl / ⌘ + G,流程图里这个键已经用来分组,所以只有 F3。

  • openSearch({ search: '质检' }) 打开查找框并填好查询。触屏设备上没有快捷键,可以像下面的示例一样放一个按钮调用它;closeSearch() 关闭查找框。
  • 只要结果时用 findNodes({ search }),它只返回匹配的节点 id,可以自己决定怎么展示。查询的类型是 FlowSearchQuery(search 和 caseSensitive)。
  • 应用有自己的全局搜索时,把 searchable 设为 false,Ctrl / ⌘ + F 就留给页面。

面板上的文字在 ConfigProvider 语言包的 findReplace 里。

上海静安店 · 收货
上海静安店 · 质检
上海静安店 · 入库
上海静安店 · 上架
上海徐汇店 · 收货
上海徐汇店 · 质检
上海徐汇店 · 入库
上海徐汇店 · 上架
杭州西湖店 · 收货
杭州西湖店 · 质检
杭州西湖店 · 入库
杭州西湖店 · 上架

控制栏 ​

DouFlowControls 放在编辑器的默认插槽里,提供撤销、重做、缩放、适应画布和整理。placement 决定它在哪个角,:history="false" 隐藏撤销和重做,:tidy="false" 隐藏整理。

“整理”沿连线按 direction 把节点一层一层排开:选中了两个以上的节点时只整理它们,否则整理全部。整理后节点群的左上角不动,锁定的节点不动,整个过程算作一步撤销,读屏会播报整理了几个节点;排好后超出视野时会缩放到能看到它们。也可以调用 tidy() 方法。

小地图 ​

DouFlowMinimap 也放在默认插槽里,画出全部节点和当前看到的范围。点击或拖动小地图可以移动画布,拖到小地图外面时视图停在边上。流程比画布大很多时才需要它。

网页 · 读取
网页 · 清洗
网页 · 去重
网页 · 统计
网页 · 导出
小程序 · 读取
小程序 · 清洗
小程序 · 去重
小程序 · 统计
小程序 · 导出
邮件 · 读取
邮件 · 清洗
邮件 · 去重
邮件 · 统计
邮件 · 导出
门店 · 读取
门店 · 清洗
门店 · 去重
门店 · 统计
门店 · 导出

适应画布和 fitView 会给四角的面板留出位置,节点不会被控制栏或小地图挡住。

只读 ​

readonly 时节点不能移动和删除,仍然可以选中、平移和缩放。

API ​

FlowEditor Props ​

名称说明类型默认值
v-model文档数据FlowDocument{ version: 1, nodes: [], edges: [] }
v-model:selection选中的节点和连线FlowSelection{ nodes: [], edges: [] }
v-model:viewport画布的位置和缩放FlowViewport{ x: 0, y: 0, zoom: 1 }
extensions扩展,见扩展(FlowExtension | FlowExtension[])[][flowKit()]
nodeTypes节点类型,见自定义节点NodeTypeSpec[]—
grid吸附网格和方向键的步长,0 关闭网格吸附number8
guides拖动时与其他节点对齐、端口吸附booleantrue
minZoom / maxZoom缩放范围number0.1 / 4
direction流程的方向,“整理”按它排列:horizontal 从左到右,vertical 从上到下'horizontal' | 'vertical''horizontal'
fitView节点测量完成后缩放到能看到全部节点booleanfalse
fitMinZoomfitView 最多缩小到多少,0 表示总是显示全部number0.5
edgeType没写 type 的连线用哪种画法,不设时用扩展的 edgeType,见连线string—
edgeTypes扩展之外的连线类型EdgeTypeSpec[]—
simpleZoom低于这个缩放比例时只画节点的外框和名字,见大型流程number0.4
portTypes端口类型的外观和连接规则,见端口类型与连接规则PortTypes—
acyclic不允许连出环booleanfalse
canConnect连线前的最后一道检查,返回 false 或一段说明拒绝(connection, doc) => boolean | string—
searchable内置的查找框(Ctrl / ⌘ + F),关闭后按键留给页面,见查找节点booleantrue
readonly只读booleanfalse
panOnScroll滚轮平移画布;关闭后只有 Ctrl / ⌘ + 滚轮缩放booleantrue
ariaLabel画布的无障碍名称string—
messages覆盖编辑器的文案,只需写要改的部分FlowMessagesOverride—

FlowEditor Events ​

名称说明参数
transaction每次修改文档时触发,包括撤销和重做,参数里有这次修改的每一步;要整份文档用 v-model(tr: FlowTransaction)
transactionCancel扩展取消了一次修改,tr.cancelReason 是原因,见取消修改(tr: FlowTransaction)
nodeClick / nodeDblclick / nodeContextmenu点击、双击、右键节点(node, event)
edgeClick / edgeContextmenu点击、右键连线(edge, event)
canvasClick / canvasContextmenu点击、右键画布空白处,point 是画布坐标;右键事件里 event.preventDefault() 不打开内置菜单(point, event)
connect连好一条线,包括改接(edge)
connectToCanvas新连线拖到空白处松开,from 是起点端口,point 是画布坐标;event.preventDefault() 不弹出节点列表,见编辑交互(from, point, event)

FlowEditor Exposes ​

名称说明类型
transact在一个事务里修改文档,算作一步撤销(fn: (tr) => void, meta?) => FlowTransaction
undo / redo撤销、重做() => boolean
canUndo / canRedo能否撤销、重做boolean
fit显示全部节点,或指定的节点(ids?: string[]) => void
zoomTo缩放到给定的比例(zoom: number) => void
zoomIn / zoomOut放大、缩小一档() => void
centerNode把节点移到画布中央,不改变缩放(id: string) => void
openSearch打开查找框,可以填好查询;searchable 关闭时返回 false(query?: Partial<FlowSearchQuery>) => boolean
closeSearch关闭查找框,没有打开时返回 false() => boolean
findNodes名字包含查找文字的节点 id,按阅读顺序(query: FlowSearchQuery) => string[]
setViewport移动视图,和用户平移一样最远到节点刚好移出视野;animate 为 true 时动画过渡(viewport: FlowViewport, animate?: boolean) => void
tidy整理节点,默认整理选中的(两个以上时)或全部,算作一步撤销(ids?: string[]) => void
toCanvas屏幕坐标转画布坐标(point: Point) => Point
getNodeRect节点在画布上的位置和尺寸(id: string) => Rect | null
exportSVG把流程导出成 SVG 文本,见导出图片(options?: FlowExportOptions) => string
exportPNG把流程导出成 PNG,见导出图片(options?: FlowImageOptions) => Promise<Blob>
staleEdges端口已经对不上的连线,见端口类型随数据变化string[]
removeStaleEdges删除这些连线,算作一步撤销,返回删除的条数() => number
insertNode新建一个节点并选中,见用代码添加节点(type: string, options?: FlowInsertOptions) => string | null
startInsertDrag从一次 pointerdown 开始拖入新节点,见拖入节点(type: string, event: PointerEvent) => boolean
paletteTypes写了 palette 的节点类型,按顺序,见拖入节点NodeTypeSpec[]
editLabel选中一条连线并开始编辑它的标签,见标签(id: string) => void
groupNodes把节点放进新分组,返回分组的 id,见分组(ids?: string[], type?: string) => string | null
ungroupNode取消分组(id: string) => boolean
leaveGroup把节点移出分组,返回移出的个数(ids?: string[]) => number

FlowControls Props ​

名称说明类型默认值
placement所在的角'top-left' | 'top-right' | 'bottom-left' | 'bottom-right''bottom-left'
history显示撤销和重做booleantrue
tidy显示整理按钮booleantrue

FlowMinimap Props ​

名称说明类型默认值
placement所在的角'top-left' | 'top-right' | 'bottom-left' | 'bottom-right''bottom-right'
width / height尺寸(px)number200 / 136