@leadal/flowstream-ui-plus

FlowStream workflow components for Vue 3
1,952
Install
npm install @leadal/flowstream-ui-plus
Latest Version:0.0.15
Vue:3
License:Proprietary
Last Updated:Oct 13, 2026
Links: npm
Maintainer: leadal

FlowStream Vue3 前端组件接入指南

FlowStream 前端运行时组件库的 npm 包名统一为 @leadal/flowstream-ui-plus。组件库基于 Vue 3 和 Element Plus,封装流程发起、工作项列表、流程操作、任务发送、任务跳转、流程图及办理轨迹等能力。

组件库公开流程操作、列表、发送、跳转、流程实例图和流程定义预览等组件,以及命令式运行时服务。流程设计与 Editor 由工作流程引擎内部提供,不在本组件库中导出。

目录

  1. 安装与配置
  2. 组件定义
    1. ui-flow-buttons
    2. ui-flow-button
    3. ui-flow-grid
    4. ui-flow-send
    5. ui-flow-jump
    6. ui-flow-diagram
    7. ui-flow-definition-preview
  3. 请求与错误处理
  4. 获取第一个办理节点
  5. 快速启动流程

1. 安装与配置

1.1 环境要求

项目 要求 说明
Node.js >= 18 组件库构建要求
pnpm >= 8 推荐包管理器
Vue >= 3.4 peer dependency
Element Plus >= 2.8 peer dependency,宿主工程负责安装和注册

1.2 安装

pnpm add @leadal/flowstream-ui-plus

# 或使用 npm
npm install @leadal/flowstream-ui-plus

1.3 全量注册

import { createApp } from 'vue'
import FlowstreamUIPlus from '@leadal/flowstream-ui-plus'
import '@leadal/flowstream-ui-plus/style.css'
import App from './App.vue'

const app = createApp(App)

app.use(FlowstreamUIPlus, {
  baseURL: import.meta.env.VITE_FLOWSTREAM_ORIGIN,
  timeout: 60_000,
  getToken: () => localStorage.getItem('access_token') || undefined,
})

app.mount('#app')

全量注册后,可直接使用 ui-flow-buttons、ui-flow-button、ui-flow-grid、ui-flow-send、ui-flow-jump、ui-flow-diagram、ui-flow-track-diagram、ui-flow-track-table 和 ui-flow-definition-preview 全局标签。流程发起调用默认导出的 flowstream.getRuntimeService().start()。

1.4 按需引入

import {
  FlowButton,
  FlowButtons,
  FlowDefinitionPreview,
  FlowDiagram,
  FlowTrackDiagram,
  FlowTrackTable,
  FlowGrid,
  FlowJump,
  FlowSend,
  configureWorkflow,
} from '@leadal/flowstream-ui-plus'
import '@leadal/flowstream-ui-plus/style.css'

configureWorkflow({
  baseURL: import.meta.env.VITE_FLOWSTREAM_ORIGIN,
  timeout: 60000,
  getToken: () => localStorage.getItem('access_token') || undefined,
})

1.5 请求前缀

baseURL 会作为所有 FlowStream 接口的统一前缀,末尾 / 会被移除。

配置 最终行为
不配置 生产构建不自动添加前缀;开发/测试源码模式默认使用 /api
/api 测试或本地代理环境显式使用 /api 前缀
http://127.0.0.1:19090 直连服务,接口形如 http://127.0.0.1:19090/flowstream/...
https://example.com/api 使用业务网关的 /api 前缀

本地代理使用 /api 时,应将 /api 转发到 FlowStream 服务,并按网关实际规则决定是否移除 /api。


2. 组件定义

组件名 全局标签 说明
UiFlowButtons ui-flow-buttons 根据工作项加载并执行流程操作
UiFlowButton ui-flow-button 单个流程按钮,是 FlowButtons 的子组件,也可单独使用
UiFlowGrid ui-flow-grid todo / done / draft 统一工作项列表
UiFlowSend ui-flow-send 完整任务发送弹窗
UiFlowJump ui-flow-jump 流程任务跳转能力
UiFlowDiagram ui-flow-diagram BPMN 流程图、运行状态和办理轨迹
UiFlowTrackDiagram ui-flow-track-diagram 单独展示 BPMN 运行轨迹流程图
UiFlowTrackTable ui-flow-track-table 单独展示办理轨迹记录表格
UiFlowDefinitionPreview ui-flow-definition-preview BPMN 流程定义预览,不查询流程实例数据

除组件外,包入口还导出 configureWorkflow、请求实例 workflowHttp、类型定义以及流程 API 方法(例如 startDraft、quickStart、getFirstHandleNodes、startNodes)。

Editor、内部基础表格和图标组件不是公共导出,不要从 @leadal/flowstream-ui-plus 引入。

公共尺寸参数

所有公开组件统一支持 size 属性,类型为 large | default | small,默认值为 default。该属性会调整组件内部按钮、表单控件、表格行高与字号;流程图类组件会在自适应父容器后调整画布缩放和图例大小。

<ui-flow-buttons size="small" />
<ui-flow-grid type="todo" size="default" :deal-user-id="userId" />
<ui-flow-diagram
  size="large"
  :process-definition-id="processDefinitionId"
  :process-instance-id="processInstanceId"
/>

size 只控制视觉规格,不替代宽高。列表、流程图和轨迹组件的实际可用区域仍由接入项目的父容器宽高决定。命令式启动同样支持 flowstream.getRuntimeService().start({ size: 'small', ... })。


2.1 ui-flow-buttons

ui-flow-buttons 根据当前工作项加载可用操作。优先使用显式传入的 workId;业务页面只有流程实例时,也可以传 processInstanceId + dealUserId,组件会自行查询并解析该用户的当前待办。发送和跳转默认由组件内部打开完整弹窗,业务页面不需要直接调用流程引擎接口;保存、启动等业务表单相关动作仍通过 execute-action 交给宿主处理。

action 处理方式
revocation / taskWithdraw 确认后执行撤回
taskRecyle 确认后执行收回;后端接口保留历史拼写 recyle
hang 确认后挂起流程实例
restore 确认后恢复流程
terminate 确认后终止流程
taskComplete 确认后办毕
taskRollback 确认后退回
taskClaim 传入 dealUserId 后执行任务拾取
turnBefore / taskTurnBefore 打开机构人员单选弹窗并执行前加签
turnAfter / taskTurnAfter 打开机构人员单选弹窗并执行后加签
taskSend 默认打开内置发送弹窗
jump / taskJump 默认打开内置跳转弹窗
save / start 触发 execute-action,由宿主处理
其他未内置动作 触发 execute-action,由宿主处理
1) 属性定义(Properties)
参数 说明 类型 必填 默认值
workId 当前工作项 ID;未传时可自动解析 string 否 —
processInstanceId 流程实例 ID;自动解析待办、挂起和终止流程时必需 string 条件 —
processDefinitionId 流程定义 ID;发送和跳转时使用 string 否 —
taskId 当前任务实例 ID;前/后加签时使用,可自动解析 string 否 —
dealUserId 当前用户 ID;自动解析待办和拾取任务时使用 string 条件 —
dealUserName 当前用户名称 string 否 —
variables 发送、办毕时提交的流程变量 Record<string, unknown> 否 {}
assignmentQueryParams 通过 extendParams 转发给扩展路由的查询参数 Record<string, unknown> 否 {}
autoResolveWork 未传 workId 时自动查询当前用户待办 boolean 否 true
autoHandleDialogs 在组件内部处理发送和跳转弹窗 boolean 否 true
forceSingleAssignee 每个下一节点仅允许选择一名办理人 boolean 否 false
dialogZIndex 内置弹窗固定层级;未传时自动高于当前 Drawer/Dialog number 否 自动
beforeAction 动作执行前钩子;返回 false 可中断,支持异步 (action, context) => boolean | void | Promise 否 —
afterAction 流程动作成功后的函数型钩子 (action, result, context) => void 否 —

context 包含 workId、流程/任务/节点 ID 和原始 workData;发送、跳转完成后还包含实际提交的 requestData。

终止操作调用 POST /flowstream/server/runtime/event/terminate,请求体为 { processInstanceIds: [processInstanceId] };workId 仅用于加载当前工作项及其可用操作,不能作为终止接口参数。

2) 事件定义(Events)
事件名称 回调参数 说明
execute-action action, context 需要宿主处理的自定义动作
after-action action, result, context 流程动作成功后触发,可用于同步业务状态和刷新列表
work-resolved context 自动解析当前用户待办成功后触发
error error: unknown 内置操作失败时触发;用户取消确认框不会触发
3) 方法定义(Methods)
方法 参数 返回 说明
getAvailableActions() — Promise<WorkflowActionItem[]> 重新加载可用按钮
resolveCurrentWork() — Promise<WorkflowActionContext> 自动解析当前待办
executeAction(button) WorkflowActionItem Promise<void> 按按钮定义执行或分发动作
4) 插槽定义(Slots)
插槽 插槽参数 说明
prefix { action } 每个流程按钮前的内容
default { action } 每个流程按钮区域的自定义内容
suffix { action } 每个流程按钮后的内容
append { actions, loading } 整个按钮组末尾的内容,仅渲染一次
5) 组件示例
<ui-flow-buttons
  :process-instance-id="task.processInstanceId"
  :process-definition-id="task.processDefinitionId"
  :deal-user-id="loginUser.id"
  :deal-user-name="loginUser.name"
  force-single-assignee
  :before-action="validateBeforeAction"
  @execute-action="handleFlowAction"
  @after-action="handleAfterAction"
  @error="handleError"
>
  <template #append>
    <el-button link type="primary" @click="handlePrint">打印</el-button>
    <el-button link type="primary" @click="handleExport">导出</el-button>
  </template>
</ui-flow-buttons>

任务“办毕”等内置操作成功后,应在 after-action 中提示并刷新列表:

function handleAfterAction(action: string, result: unknown) {
  ElMessage.success('操作成功')
  gridRef.value?.loadTableData()
}

2.2 ui-flow-button

ui-flow-button 是按钮组内部使用的单按钮子组件,也可以单独导入。

1) 属性定义(Properties)
参数 说明 类型 默认值
type 预设动作类型,决定默认文字和图标 string —
label 覆盖预设按钮文字 string —

内置类型包括 save、start、revocation、taskWithdraw、taskRecyle、hang、restore、terminate、jump、taskJump、taskComplete、taskSend、taskRollback、taskClaim、turnBefore、taskTurnBefore、turnAfter 和 taskTurnAfter。

2) 事件定义(Events)
类型 名称 参数 说明
Event click type?: string 点击后返回对应动作类型
3) 插槽定义(Slots)
插槽 参数 说明
default — 自定义按钮内容;未提供时显示 label,再回退到 type
4) 组件示例
<ui-flow-button type="save" label="保存草稿" @click="saveForm" />

2.3 ui-flow-grid

ui-flow-grid 是待办、已办和草稿统一列表组件,内部完成接口请求、分页、状态显示和行操作。type 必填。

内置列

  • todo / done:业务标题 businessName、当前环节 activityName、发送人 assigneesNames、发送时间 startTime。
  • draft:业务标题 title、当前环节 currentActivity、创建人 createUserName、创建时间 createdTime。
  • done 根据 stateName 显示状态,draft 根据 stateLabel 显示状态。

发送人列必须读取接口字段 assigneesNames,不使用 assignees 或 previousAssignee。

done 状态映射:

stateName 显示文本
executing 审批中
completed 已完成
deleted 已删除
canceled 已取消
withdrawed 已撤回
recyled 已回收
rollbacked 已退回
jumped 已跳转
1) 属性定义(Properties)
参数 说明 类型 可选值 默认值
type 列表类型 string todo / done / draft —
dealUserId 当前用户 ID;todo/done 查询使用 assignee,draft 查询使用 createUserId string — ''
appId 草稿查询的应用 ID string — ''
appModuleId 草稿查询的应用模块 ID string — ''
2) 事件定义(Events)
事件名称 回调参数 说明
on-handle { action, workData } 行办理、查看或新建草稿
error error: unknown 列表加载失败

action 规则:todo 办理为 view,done 查看为 handle,draft 查看为 view,调用 create(flow) 新建草稿为 create。

todo/done 的 workData 会统一保留并补齐 workId、processDefinitionId、processInstanceId、activityId 和 activityName。

3) 方法定义(Methods)
名称 类型 说明
loadTableData() Method 按当前 type、用户和页码重新加载数据
create(flow) Method 生成默认业务标题并触发 on-handle 的 create 动作
data Ref 当前列表数据
loading Ref 加载状态
pageConfig Reactive { currentPage, pageSize, total }
4) 组件示例
<script setup lang="ts">
import { ref } from 'vue'
import { FlowGrid } from '@leadal/flowstream-ui-plus'

const gridRef = ref<InstanceType<typeof FlowGrid>>()

function handleWork({ action, workData }: {
  action: 'view' | 'handle' | 'create'
  workData: Record<string, unknown>
}) {
  console.log(action, workData)
}
</script>

<template>
  <div class="flow-grid-page">
    <ui-flow-grid
      ref="gridRef"
      type="todo"
      :deal-user-id="currentUserId"
      @on-handle="handleWork"
      @error="handleError"
    />
  </div>
</template>

<style scoped>
.flow-grid-page {
  width: 100%;
  height: 100%;
  min-height: 500px;
  box-sizing: border-box;
}
</style>

2.4 ui-flow-send

ui-flow-send 是完整的任务发送弹窗,不只是一个“发送”按钮。组件内置以下交互:

  • 根据当前流程定义、节点和 variables 调用 getSatisfiedSuccedingFlowNodes 计算实际可达的下一环节;后端仍返回网关时继续查询后继;
  • 只有查询结果为唯一人工节点,且 checkSend 返回的节点与之相同,才展示办理人确认框直接发送;其余情况打开完整发送弹窗;
  • 按下一环节加载候选办理人,支持列表和懒加载树;
  • 选择各下一环节的办理人;
  • 流程变量和办理人查询扩展参数由接入方传入,弹窗内不提供编辑页签;
  • 填写审批意见;
  • 确认后调用任务发送接口,成功后关闭弹窗并提示“发送成功”。

办理人候选数据通过 POST /flowstream/server/assignment/event/query 加载。业务路由需要额外上下文时,可通过 assignmentQueryParams 传入任意数量的扩展参数,也可以不传;组件将其整体放入请求体的 extendParams。请求根对象中的 processDefinitionId、processInstanceId、activityId、userId、parentId 和 ntype 始终由组件维护。动态路由配置为“流程启动者”时,后端通过 processInstanceId 读取该实例的起草人。variables 为空时,条件查询返回所有可能后继,不能视为已确定的办理路线。

1) 属性定义(Properties)
参数 说明 类型 必填 默认值
modelValue 弹窗可见状态,使用 v-model boolean 否 false
processDefinitionId 流程定义 ID string | number 是 —
activity 当前节点,至少包含 activityId,可带 activityName object 是 —
workId 当前工作项 ID string | number 是 —
processInstanceId 流程实例 ID;动态路由以流程启动者为基准时必需 string | number 条件 ''
variables 当前业务流程变量 Record<string, unknown> 否 {}
assignmentQueryParams 通过 extendParams 转发给扩展路由的查询参数 Record<string, unknown> 否 {}
dealUser 当前用户,可传 id 或 userId object 否 {}
bpmnXml BPMN XML;用于辅助判断下一节点是单人还是多人办理 string 否 ''
showTrigger 是否显示组件自身的发送按钮 boolean 否 true
dialogTitle 弹窗标题 string 否 '发送'
dialogWidth 弹窗宽度 string 否 '1200px'
zIndex 固定弹层层级;未传时自动高于当前 Drawer/Dialog number 否 自动
defaultOpinion 每次打开弹窗时的默认意见 string 否 ''
forceSingleAssignee 是否强制每个下一节点只能选择一个办理人 boolean 否 false
2) 事件定义(Events)
事件名称 回调参数 说明
update:modelValue visible: boolean v-model 更新
click — 点击组件自身发送按钮时触发,随后组件会自行打开弹窗
open — 开始执行发送前检查;未命中时继续打开完整弹窗
close — 弹窗完成关闭
next-nodes-resolved nodes: FlowNode[] 下一环节解析成功
before-send data 请求发送前触发,参数是即将提交的数据
after-send result: ApiResponse 发送成功后触发
error error: unknown 下一环节、候选人或发送请求失败
3) 方法定义(Methods)
名称 类型 说明
open() Method 执行发送前检查;未命中时打开弹窗并解析下一环节
close() Method 关闭弹窗
getNextNode(variables?) Method 根据变量重新解析下一环节
assembleData() Method 组装 { workId, flowNodeAssignees, variables, opinion }
send(formData?) Method 提交发送;不传参数时使用 assembleData()
visible Ref 内部弹窗状态
loading Ref 发送状态
checkingSend Ref 发送前检查状态
nodeLoading Ref 下一环节计算状态
nodeResolved Ref 下一环节是否已完成计算
nextNodes Ref 下一环节列表
4) 组件示例

ui-flow-buttons 已默认内置 FlowSend。以下手动组合方式仅用于需要完全自定义发送弹窗编排的场景,此时应关闭自动弹窗:

<script setup lang="ts">
import { ref } from 'vue'
import { FlowButtons, FlowSend } from '@leadal/flowstream-ui-plus'

const sendVisible = ref(false)
const assignmentQueryParams = {
  projectId: currentProject.id,
  tenantId: currentTenant.id,
}

function handleFlowAction(action: string) {
  if (action === 'taskSend') sendVisible.value = true
}

function handleAfterSend() {
  sendVisible.value = false
  gridRef.value?.loadTableData()
}
</script>

<template>
  <ui-flow-buttons
    :work-id="task.workId"
    :process-instance-id="task.processInstanceId"
    :auto-handle-dialogs="false"
    @execute-action="handleFlowAction"
  />

  <ui-flow-send
    v-model="sendVisible"
    :process-definition-id="task.processDefinitionId"
    :process-instance-id="task.processInstanceId"
    :activity="{
      activityId: task.activityId,
      activityName: task.activityName,
    }"
    :work-id="task.workId"
    :deal-user="currentUser"
    :variables="variables"
    :assignment-query-params="assignmentQueryParams"
    :show-trigger="false"
    default-opinion="同意"
    @after-send="handleAfterSend"
    @error="handleError"
  />
</template>

也可以保留默认 showTrigger=true,直接点击 FlowSend 自身按钮打开弹窗。推荐使用 v-model 控制弹窗;需要命令式调用时可使用 sendRef.value?.open()。


2.5 ui-flow-jump

ui-flow-jump 提供跳转按钮、内置节点/办理人选择弹窗和跳转接口封装。选择开始节点后,组件通过办理人接口懒加载组织树;如果节点没有返回办理人,会回填 dealUser。跳转不提供变量编辑,请求固定提交 variables: {}。

1) 属性定义(Properties)
参数 说明 类型 必填
processDefinitionId 流程定义 ID string | number 是
workId 当前待办工作项 ID string | number 确认跳转时是
processInstanceId 流程实例 ID;动态路由以流程启动者为基准时必需 string | number 条件
dealUser 当前用户,支持 { id, userId, name } object 否
assignmentQueryParams 通过 extendParams 转发给扩展路由的查询参数 Record<string, unknown> 否
modelValue 弹窗显示状态,支持 v-model boolean 否
showTrigger 是否显示组件自带跳转按钮,默认 true boolean 否
dialogTitle 弹窗标题,默认“跳转” string 否
dialogWidth 弹窗宽度,默认 960px string 否
zIndex 固定弹层层级;未传时自动高于当前 Drawer/Dialog number 否
2) 事件定义(Events)
事件名称 回调参数 说明
update:modelValue visible 弹窗显示状态变化
click — 点击跳转按钮
open — 弹窗打开
close — 弹窗关闭
before-jump data 提交跳转前
after-jump result 跳转成功后
error error 加载节点、办理人或提交跳转失败
3) 方法定义(Methods)
名称 类型 说明
open() / close() Method 打开或关闭内置弹窗
getStartNodes() Method 加载可跳转用户任务节点
assembleData(targetNode?, assigneeId?) Method 组装跳转数据,变量固定为空对象
jump(formData?) Method 执行跳转
loading Ref 跳转请求状态
startNodeList Ref 可跳转节点列表
4) 组件示例
<script setup lang="ts">
import { ref } from 'vue'
import { FlowJump } from '@leadal/flowstream-ui-plus'

const jumpVisible = ref(false)
const assignmentQueryParams = { deptCode: 'D1001' }
</script>

<template>
  <ui-flow-jump
    v-model="jumpVisible"
    :process-definition-id="task.processDefinitionId"
    :process-instance-id="task.processInstanceId"
    :work-id="task.workId"
    :deal-user="currentUser"
    :assignment-query-params="assignmentQueryParams"
    :show-trigger="false"
    @before-jump="handleBeforeJump"
    @after-jump="handleAfterJump"
    @error="handleError"
  />
</template>

保留默认 showTrigger=true 时,点击组件自身按钮即可打开弹窗。与 ui-flow-buttons 配合时,将其设为 false,在按钮组触发 taskJump 或 jump 后把 jumpVisible 设为 true。


2.6 ui-flow-diagram

ui-flow-diagram 是组合组件,上方使用 ui-flow-track-diagram 渲染 BPMN 运行轨迹,下方保留“办理轨迹”标题并使用 ui-flow-track-table 展示办理记录。独立的 ui-flow-track-table 本身不包含标题。父容器必须有明确高度,否则流程图可能看起来是一片空白。

1) 属性定义(Properties)
参数 说明 类型 必填
processDefinitionId 流程定义 ID,用于下载 BPMN XML string 是
processInstanceId 流程实例 ID,用于查询运行状态和轨迹 string 是
2) 事件定义(Events)
事件名称 回调参数 说明
loaded — BPMN、运行状态和轨迹全部加载并渲染完成
error error: unknown 任一加载或渲染步骤失败
3) 方法定义(Methods)
名称 类型 说明
refresh() Method 重新加载 BPMN、运行状态和办理轨迹
viewer ShallowRef bpmn-js Viewer 实例
trackData Ref 办理轨迹数据
4) 节点颜色
状态 颜色 说明
当前环节 executing #ffd37e 正在办理
已办理节点 / StartEvent #98e5b5 已办理或开始节点
EndEvent #f14b12 结束节点
其余 Task #eee 未办理节点
5) 组件示例
<script setup lang="ts">
import { ref } from 'vue'
import { FlowDiagram } from '@leadal/flowstream-ui-plus'

const diagramRef = ref<InstanceType<typeof FlowDiagram>>()
</script>

<template>
  <div class="diagram-container">
    <ui-flow-diagram
      ref="diagramRef"
      :process-definition-id="task.processDefinitionId"
      :process-instance-id="task.processInstanceId"
      @loaded="handleDiagramLoaded"
      @error="handleError"
    />
  </div>
</template>

<style scoped>
.diagram-container {
  height: 700px;
}
</style>

任务流转后可调用 diagramRef.value?.refresh() 刷新节点颜色和办理轨迹。

6) 独立使用轨迹流程图或轨迹表格

业务页面只需要其中一部分时,可以按需引入两个拆分组件:

<script setup lang="ts">
import { ref } from 'vue'
import {
  FlowTrackDiagram,
  FlowTrackTable,
} from '@leadal/flowstream-ui-plus'

const trackDiagramRef = ref<InstanceType<typeof FlowTrackDiagram>>()
const trackTableRef = ref<InstanceType<typeof FlowTrackTable>>()
</script>

<template>
  <div style="height: 420px">
    <ui-flow-track-diagram
      ref="trackDiagramRef"
      :process-definition-id="task.processDefinitionId"
      :process-instance-id="task.processInstanceId"
      @error="handleError"
    />
  </div>

  <div style="height: 360px">
    <ui-flow-track-table
      ref="trackTableRef"
      :process-instance-id="task.processInstanceId"
      @error="handleError"
    />
  </div>
</template>

FlowTrackDiagram 公开 refresh()、viewer 和 viewState;FlowTrackTable 是不带标题、折叠按钮和额外内边距的纯表格,公开 refresh() 和 trackData。两个组件都提供 loaded、error 事件,且父容器均应设置明确高度。


2.7 ui-flow-definition-preview

ui-flow-definition-preview 用于只读预览流程定义。组件只获取并渲染 BPMN XML,不查询流程实例状态和办理轨迹。父容器必须有明确高度。

1) 属性定义(Properties)
参数 说明 类型 默认值
processDefinitionId 已发布的流程定义 ID;未传 bpmnXml 时必填 string ''
bpmnXml 直接预览 BPMN XML,传入后优先于 processDefinitionId string ''
fitViewport 加载及容器尺寸变化后是否自动适应可视区域 boolean true
2) 事件定义(Events)
事件名称 回调参数 说明
loaded — BPMN XML 加载并渲染完成
error error: unknown 下载或渲染流程定义失败
3) 方法定义(Methods)
名称 说明
refresh() 重新下载或读取 XML 并渲染流程定义
fitViewport() 立即将流程图缩放到适合当前容器
viewer bpmn-js Viewer 实例
4) 已发布流程定义示例
<template>
  <div class="preview-container">
    <ui-flow-definition-preview
      :process-definition-id="processDefinitionId"
      @loaded="handleLoaded"
      @error="handleError"
    />
  </div>
</template>

<style scoped>
.preview-container {
  width: 100%;
  height: 600px;
}
</style>
5) 未发布 XML 预览示例
<ui-flow-definition-preview :bpmn-xml="modelerXml" />

同时传入 bpmnXml 和 processDefinitionId 时,组件直接渲染 bpmnXml,不会调用 BPMN 下载接口。


3. 请求与错误处理

3.1 成功响应

组件将服务端 code 为 0 或 200 的响应视为成功。其他 code 会被转换为 Error,错误信息优先读取 msg,其次读取 message。

3.2 认证

通过全量注册参数或 configureWorkflow() 设置 getToken。返回非空 token 时,请求头会写入:

Authorization: <token>

3.3 常见排查

现象 优先检查
请求出现 Cannot POST /api/... 本地代理是否配置、是否需要移除 /api,以及 baseURL 是否只在测试环境设为 /api
点击发送没有反应 是否传入了 workId,或可用于自动解析的 processInstanceId + dealUserId
提示缺少流程定义或节点信息 待办数据是否包含 processDefinitionId、processInstanceId 和 activityId
sendRef.open is not a function 是否引用了当前 Vue3 包的完整 FlowSend;推荐改用 v-model 打开
办毕成功后页面无反馈 是否监听 ui-flow-buttons 的 after-action 并提示、刷新列表
流程图空白 父容器是否有明确高度,流程定义 ID、流程实例 ID 和 BPMN 下载接口是否正确
发送人显示错误 Grid 列必须使用 assigneesNames,不是 assignees

3.4 任务发送请求结构

ui-flow-send 最终向 /flowstream/server/task/event/send 提交:

{
  "workId": "工作项ID",
  "flowNodeAssignees": [
    {
      "activityId": "下一环节ID",
      "assignees": [
        {
          "name": "用户ID",
          "userId": "用户ID"
        }
      ]
    }
  ],
  "variables": {},
  "opinion": "同意"
}

发送必须使用当前有效工作项的 workId。若服务端返回 the current work is null!,应重新查询当前用户待办,并使用最新工作项 ID,不能重复发送已流转或已失效的工作项。


4. 获取第一个办理节点

已知流程定义 ID 时,可获取第一个需要人工办理的节点:

import {
  getFirstHandleNodes,
  type FlowNode,
} from '@leadal/flowstream-ui-plus'

const result = await getFirstHandleNodes({
  processDefinitionId,
})
const firstHandleNodes: FlowNode[] = result.data || []

getFirstHandleNodes() 调用 POST /flowstream/server/model/event/get/firsthandle。服务端会跳过开始事件、网关和中间事件,返回各分支上遇到的第一个 USER_TASK,因此结果必须按数组处理;纯自动流程返回空数组,不属于失败。

flowStartNodeList(args) 暂时保留为兼容别名,但已切换到 /firsthandle。跳转组件内部使用的 startNodes() 仍调用 /event/get/usertasks,其行为不受影响。


5. 快速启动流程

流程发起不再要求业务模板放置组件,统一调用默认导出的命令式服务。内部会完成首办节点解析、快速启动、下一节点解析、候选办理人查询并自动打开发送弹窗。

import flowstream from '@leadal/flowstream-ui-plus'

async function submitBusiness() {
  const result = await flowstream.getRuntimeService().start({
    processDefinitionId,
    draftUserId: currentUser.id,
    draftUserName: currentUser.name,
    business: {
      key: `borrow:${borrowId}`,
      name: borrowTitle,
    },
    variables,
    assignmentQueryParams: {
      projectId: currentProject.id,
      tenantId: currentTenant.id,
    },
    async onBeforeStart(startArgs) {
      // 可执行同步校验,也可以 await 业务项目自己的表单弹窗。
      const formData = await openBusinessForm()
      if (!formData) return false
      startArgs.variables = { ...startArgs.variables, ...formData }
      return true
    },
    async onBeforeSend(context) {
      // false:实例已经创建,但不打开审批人选择弹窗。
      return validateBeforeSend(context)
    },
    onStarted(result) {
      saveFlowRelation(result.processInstanceId)
    },
    onAfterSend({ sendData }) {
      // 下一节点审批人:sendData.flowNodeAssignees[].assignees[].userId
      refreshBusinessList()
    },
    onClose() {
      // 未发送就关闭弹窗时,运行时服务会撤销刚创建的流程实例。
    },
    onError(error) {
      console.error(error.phase, error.message)
    },
  })
  if (result === false) return
}

onBeforeStart 在首办节点查询和 quickStart 之前执行;返回 false 时 start() 返回 false,不会创建流程实例。onBeforeSend 在实例创建成功后、发送弹窗打开前执行;返回 false 时 start() 仍返回流程实例结果,但不会弹窗,并保留当前会话。之后调用 await flowstream.getRuntimeService().open() 会重新执行 onBeforeSend,通过后才打开弹窗;若决定放弃,调用 close() 会撤销该实例并释放会话。

两个前置钩子都支持 boolean | Promise<boolean>。因此业务项目需要“弹表单、校验通过后再启动”时,应让业务弹窗封装成 Promise,而不是由流程组件识别业务字段:

let finishBeforeStart: ((allowed: boolean) => void) | undefined

function waitForBusinessForm() {
  businessDialogVisible.value = true
  return new Promise<boolean>(resolve => {
    finishBeforeStart = resolve
  })
}

async function confirmBusinessForm() {
  const valid = await businessFormRef.value?.validate().catch(() => false)
  if (!valid) return
  businessDialogVisible.value = false
  finishBeforeStart?.(true)
  finishBeforeStart = undefined
}

function cancelBusinessForm() {
  businessDialogVisible.value = false
  finishBeforeStart?.(false)
  finishBeforeStart = undefined
}

await flowstream.getRuntimeService().start({
  processDefinitionId,
  draftUserId: currentUser.id,
  draftUserName: currentUser.name,
  onBeforeStart: waitForBusinessForm,
})

业务弹窗通过右上角关闭、路由离开或组件卸载时也必须 resolve(false),避免 start() 一直处于等待状态。singleAssignee 默认为 false,发送弹窗采用下一节点接口返回的 dealType;显式设置为 true 时会无视节点办理方式并强制单选。也可在启动参数中传入 dialogTitle、dialogWidth、defaultOpinion、bpmnXml 和 assignmentQueryParams。

quickStart()、getFirstHandleNodes()、getSatisfiedSuccedingFlowNodes()、nextSendNode()、nodeAssistant() 和 sendTask() 仍作为底层 API 导出,供组件内部及高级扩展使用;普通业务项目应优先调用 flowstream.getRuntimeService().start(),不要自行复制流程编排。

Version History

Version Released Vue License
0.0.15 ^3.4.0 Proprietary
0.0.14 ^3.4.0 Proprietary
0.0.13 ^3.4.0 Proprietary
0.0.12 ^3.4.0 Proprietary
0.0.11 ^3.4.0 Proprietary