Skip to content

流程表单上下文变量

流程表单(NORMAL 类型)运行在发起页、待办详情、已办详情、我的流程详情等不同场景中。很多时候,字段的显示、禁用、必填状态需要根据当前流程节点、流程状态、任务 ID 或视图类型动态变化。

RuoYi Office 在流程表单运行时内置了 bpmProcess 上下文变量,表单设计器中的动态属性和事件脚本都可以直接读取这些流程信息。

适用场景

  • 某个字段只在指定审批节点显示。
  • 审批中字段只读,退回到发起人后可编辑。
  • 审批人节点需要补填某个字段,并设为必填。
  • 同一张流程表单在发起、待办、已办、抄送查看时展示不同控件。
  • 调试流程表单时,需要确认当前页面拿到的流程实例、任务、节点信息是否正确。

运行机制

流程表单运行页会在加载审批详情后构建流程上下文,并注入到 form-create:

text
审批详情接口
  -> 流程实例、流程定义、待办任务、路由参数
  -> 构建 bpmProcess 上下文
  -> 注入到 form-create globalData/globalVariable
  -> 设计器动态属性和事件脚本读取变量

PC 端核心代码位于:

文件说明
ruoyi-office-vben/apps/web-antd/src/components/form-create/bpm-context.ts流程上下文变量定义、注入、调试输出
ruoyi-office-vben/apps/web-antd/src/views/bpm/form/designer/index.vue设计器中注册流程上下文变量
ruoyi-office-vben/apps/web-antd/src/views/bpm/processInstance/create/modules/form.vue发起流程时注入上下文
ruoyi-office-vben/apps/web-antd/src/views/bpm/processInstance/detail/index.vue待办、已办、我的流程详情中注入上下文

可用变量

运行时可通过 $globalData.bpmProcess 读取完整对象,也可以读取对象下的具体字段。

字段示例表达式说明
activityId$globalData.bpmProcess.activityId当前活动节点 ID,抄送或历史查看时可能存在
businessKey$globalData.bpmProcess.businessKey业务主键,绑定物理表或业务表单时常用
currentUserId$globalData.bpmProcess.currentUserId当前登录用户 ID
formCategory$globalData.bpmProcess.formCategory表单分类,例如 normalbound
formId$globalData.bpmProcess.formId流程表单 ID
formType$globalData.bpmProcess.formType表单类型,NORMAL 通常为 10
isApproval$globalData.bpmProcess.isApproval是否处于审批态
isEditable$globalData.bpmProcess.isEditable当前详情页表单是否可编辑
nodeKey$globalData.bpmProcess.nodeKey当前节点 Key,通常来自路由 nodeKey
nodeKeyName$globalData.bpmProcess.nodeKeyName当前节点名称,例如 审批人
processDefinitionId$globalData.bpmProcess.processDefinitionId流程定义 ID
processDefinitionName$globalData.bpmProcess.processDefinitionName流程定义名称
processInstanceId$globalData.bpmProcess.processInstanceId流程实例 ID
processInstanceName$globalData.bpmProcess.processInstanceName流程实例名称
processStatus$globalData.bpmProcess.processStatus流程状态,例如审批中通常为 1
taskId$globalData.bpmProcess.taskId当前待办任务 ID
taskName$globalData.bpmProcess.taskName当前任务名称
viewType$globalData.bpmProcess.viewType视图类型:createtodomydonecopy

设计器中也会注册同名全局变量,变量名为 bpmProcess + 字段名首字母大写,例如:

全局变量等价字段
bpmProcessNodeKey$globalData.bpmProcess.nodeKey
bpmProcessProcessStatus$globalData.bpmProcess.processStatus
bpmProcessTaskId$globalData.bpmProcess.taskId
bpmProcessViewType$globalData.bpmProcess.viewType

在动态属性中使用

在流程表单设计器中选中组件,进入右侧属性面板,可以在动态属性中配置:

  • hidden:控制隐藏。
  • props.disabled:控制禁用。
  • $required:控制必填。

指定节点才显示

hidden 写入:

js
GET_DATA("$globalData.bpmProcess.nodeKey") !== "Activity__23729988711775397719570"

含义:只有当前节点 Key 等于 Activity__23729988711775397719570 时显示,否则隐藏。

只有待办审批态可编辑

props.disabled 写入:

js
GET_DATA("$globalData.bpmProcess.viewType") !== "todo"

含义:不是待办详情时禁用字段。

如果还要判断审批态:

js
GET_DATA("$globalData.bpmProcess.viewType") !== "todo" ||
GET_DATA("$globalData.bpmProcess.isApproval") !== true

审批中设为必填

$required 写入:

js
GET_DATA("$globalData.bpmProcess.processStatus") == 1

建议使用宽松比较 ==,兼容状态值为数字或字符串的情况。

多节点控制

js
[
  "Activity__23729988711775397719570",
  "Activity__finance_approve"
].includes(GET_DATA("$globalData.bpmProcess.nodeKey"))

该表达式可用于 $requiredprops.disabled。如果用于 hidden,通常需要取反:

js
![
  "Activity__23729988711775397719570",
  "Activity__finance_approve"
].includes(GET_DATA("$globalData.bpmProcess.nodeKey"))

在事件脚本中使用

如果动态属性无法满足复杂逻辑,可以在表单事件中编写脚本。常用事件是 onMounted

进入“基础能力 → 表单设计器 → 编辑表单”,打开“表单事件”,选择 onMounted,写入:

js
function onMounted(api) {
  const bpm =
    api.getData?.("$globalData.bpmProcess") ||
    window.__bpmProcessContext ||
    {};

  console.warn("[表单脚本读取 BPM]", bpm);

  const isTodo = bpm.viewType === "todo";
  const isApproveNode =
    bpm.nodeKey === "Activity__23729988711775397719570";
  const isRunning = String(bpm.processStatus) === "1";

  api.hidden?.(!(isTodo && isApproveNode), "fieldName");
  api.disabled?.(isRunning, "fieldName");
}

fieldName 替换为组件真实字段名。字段名可在表单设计器中选中组件后查看。

常见脚本案例

审批节点回填字段

审批人节点显示并允许填写 approveAmount,其他场景隐藏:

js
function onMounted(api) {
  const bpm = api.getData?.("$globalData.bpmProcess") || {};
  const canInput =
    bpm.viewType === "todo" &&
    bpm.nodeKey === "Activity__23729988711775397719570";

  api.hidden?.(!canInput, "approveAmount");
  api.disabled?.(!canInput, "approveAmount");

  if (canInput) {
    const rule = api.getRule?.("approveAmount");
    if (rule) {
      rule.validate = [
        {
          required: true,
          message: "审批金额不能为空",
          trigger: "change",
        },
      ];
    }
  }
}

发起页可编辑,审批页只读

js
function onMounted(api) {
  const bpm = api.getData?.("$globalData.bpmProcess") || {};
  const readonly = bpm.viewType !== "create";

  ["amount", "reason", "remark"].forEach((field) => {
    api.disabled?.(readonly, field);
  });
}

退回到发起人后重新编辑

isEditable 会根据流程状态和当前待办任务判断当前表单是否可编辑:

js
function onMounted(api) {
  const bpm = api.getData?.("$globalData.bpmProcess") || {};

  ["amount", "reason", "attachment"].forEach((field) => {
    api.disabled?.(!bpm.isEditable, field);
  });
}

不同节点显示不同字段

js
function onMounted(api) {
  const bpm = api.getData?.("$globalData.bpmProcess") || {};

  const isDeptApprove = bpm.nodeKey === "Activity__dept_approve";
  const isFinanceApprove = bpm.nodeKey === "Activity__finance_approve";

  api.hidden?.(!isDeptApprove, "deptApproveOpinion");
  api.hidden?.(!isFinanceApprove, "financeApproveOpinion");
}

根据流程状态控制

js
function onMounted(api) {
  const bpm = api.getData?.("$globalData.bpmProcess") || {};
  const status = String(bpm.processStatus);

  // 1 审批中,2 审批通过,3 审批不通过,4 已取消。
  api.hidden?.(status !== "1", "runningOnlyField");
  api.disabled?.(["2", "3", "4"].includes(status), "amount");
}

调试方法

运行时会将上下文挂载到浏览器 window,便于调试。

打开浏览器控制台,执行:

js
window.__bpmProcessContext

查看完整变量表:

js
window.__bpmProcessVariables

读取某个字段:

js
window.__bpmProcessContext.nodeKey
window.__bpmProcessContext.processStatus
window.__bpmProcessVariables["$globalData.bpmProcess.nodeKey"]
window.__bpmProcessVariables.bpmProcessNodeKey

页面加载时也会在控制台输出 [BPM流程上下文] 流程详情页[BPM流程上下文] 流程发起页,展开后可查看:

  • $globalData.bpmProcess
  • rows
  • window.__bpmProcessContext
  • window.__bpmProcessVariables

推荐配置方式

优先级建议如下:

方式适用场景
动态属性简单显隐、禁用、必填
表单事件脚本多字段联动、复杂判断、批量控制
业务表单字段权限CUSTOM 业务表单节点权限
定制页面代码需要复杂业务交互、接口保存、明细表生命周期

流程表单的动态属性适合低代码配置。若审批节点需要保存复杂业务字段,建议改造为业务表单,并参考 业务表单接入

常见问题

控制台能看到变量,但动态属性不生效

检查表达式是否写在正确属性上:

  • 隐藏写 hidden
  • 禁用写 props.disabled
  • 必填写 $required

同时确认字段是流程表单组件自身字段,而不是业务表单自定义组件内部字段。

nodeKey 为空

通常是入口 URL 没有携带 nodeKey,或当前是历史查看、抄送查看场景。可以改用 taskNamenodeKeyNameviewType 判断。

activityId 为空

activityId 并非所有入口都有值。待办详情中优先使用 nodeKeytaskId

processStatus 是数字还是字符串

不同表达式环境可能存在数字和字符串差异。脚本中建议统一转字符串:

js
String(bpm.processStatus) === "1"

动态表达式中建议使用宽松比较:

js
GET_DATA("$globalData.bpmProcess.processStatus") == 1

事件脚本没有执行

先确认是否保存了表单事件,并重新打开详情页。若只是做字段显隐、禁用、必填,优先使用动态属性,不依赖事件脚本。

修改表单后旧流程实例是否立即生效

流程详情页会优先加载当前表单配置,让设计器修改后的动态规则便于验证。但已发布流程的表单配置与流程定义快照仍需结合实际发布策略确认。正式流程调整后建议重新发布流程模型。

联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版