NocoBase 表达式表:为工作流动态表达式计算准备可配置规则的数据表方案
2026/9/14 5:04:06 网站建设 项目流程

NocoBase 表达式表:为工作流动态表达式计算准备可配置规则的数据表方案

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

表达式表(Expression Collection)是 NocoBase 数据建模体系中专门面向工作流"动态表达式计算"场景的一种表模板。它把"计算规则/公式"当作可管理的数据存表:每行公式可以引用不同数据模型中的字段作为变量、可以指定不同的计算引擎,再通过关联关系挂接到业务数据上,最终由工作流中的动态计算节点在运行时按行加载并求值。读完本文,你将掌握表达式模板表的创建方式、字段构成、业务数据与公式的关联设计,以及动态计算节点在源码层面的执行链路。

表达式表在数据建模中的定位

在 NocoBase 的数据表类型体系中,除了普通表、树表、日历表、视图表、SQL 表等常规形态外,还存在若干为特定业务场景定制的表模板。数据建模概述的表类型说明中明确列出了这一行:表达式表 —— 用于工作流的动态表达式场景

与普通业务表不同,表达式表里存放的不是业务实体,而是"规则本身":针对特定表数据模型的一条计算规则。这样做的价值在于把公式从工作流配置中抽离出来,变成可以被增删改查、可以被按类别组织、可以随业务数据一起被查询加载的数据行,从而实现"同一套流程,不同数据走不同公式"的动态计算能力。

创建"表达式"模板表

在工作流内使用动态表达式运算节点之前,需要先在数据表管理工具中创建一张"表达式"模板表,用于存放不同的表达式。这张模板表由插件@nocobase/plugin-workflow-dynamic-calculation的客户端代码以集合模板的形式注册,其定义见 ExpressionCollectionTemplate.ts:

export class ExpressionCollectionTemplate extends CollectionTemplate { name = 'expression'; title = '{{t("Expression collection")}}'; order = 4; color = 'orange'; default = { createdBy: true, updatedBy: true, createdAt: true, updatedAt: true, fields: [ { name: 'engine', type: 'string', interface: 'radioGroup', uiSchema: { type: 'string', title: '{{t("Calculation engine")}}', 'x-component': 'Radio.Group', enum: getOptions(), default: 'formula.js', }, }, { name: 'sourceCollection', type: 'string', interface: 'select', uiSchema: { type: 'string', title: '{{t("Collection")}}', 'x-component': 'CollectionSelect', }, }, { name: 'expression', type: 'text', interface: 'expression', uiSchema: { type: 'string', title: '{{t("Expression")}}', 'x-component': 'DynamicExpression', }, }, ], }; // ... }

从这段模板定义(ExpressionCollectionTemplate.ts#L13-L71)可以读出表达式表的完整字段构成:

字段类型/界面说明
enginestring / 单选按钮组(Radio.Group指定该行公式使用的计算引擎,选项来自@nocobase/evaluators/clientgetOptions(),模板中的默认值为formula.js
sourceCollectionstring / 数据表选择(CollectionSelect指定该公式针对的数据表(数据模型),即公式的适用对象
expressiontext / 表达式字段(x-component: DynamicExpression表达式正文,即计算规则的字符串表达
createdBy/updatedBy/createdAt/updatedAt系统审计字段模板默认开启,记录公式行的创建与修改痕迹

值得注意的一个细节:模板里表达式列使用的字段接口是expression,这是一个由插件注册的自定义字段类型。服务端实现见 expression-field.ts:

export class ExpressionField extends Field { get dataType() { return DataTypes.TEXT; } }

ExpressionField继承自@nocobase/databaseField,落库数据类型为TEXT,保证较长的公式字符串也能完整存储(见 expression-field.ts#L16-L19)。插件的load方法把该字段类型注册进数据库,并同时向工作流插件注册dynamic-calculation指令,这两处注册逻辑见 Plugin.ts#L17-L24:

async load() { this.db.registerFieldTypes({ expression: ExpressionField, }); const workflowPlugin = this.app.getPlugin<WorkflowPlugin>(WorkflowPlugin); workflowPlugin.registerInstruction('dynamic-calculation', DynamicCalculation); }

也就是说,表达式表(字段类型expression)与动态计算指令(dynamic-calculation)是同一个插件成对提供的能力:前者负责"规则的存储",后者负责"规则的运行时求值"。

版本提示:当前仓库中 该插件的文档 frontmatter 已标注deprecated: true(本插件已废弃)。在使用表达式表 + 动态计算指令这套方案时,请以你所使用的 NocoBase 版本中该插件的实际可用状态为准;若插件不可用,可参考下文的工作流"计算"节点作为静态表达式的替代。

录入表达式数据

创建好模板表后,可以为该表添加一个表格区块,录入若干条公式数据。理解方式上,表达式模板表中每行数据都可以被理解为针对特定表数据模型的一个计算规则

  • 每行公式可以使用不同数据表的数据模型中的字段值作为变量,因此一张表达式表可以同时服务于多个业务对象;
  • 每行公式可以使用不同的计算引擎,即engine列逐行指定,同一张表内的各行规则互不干扰;
  • 结合sourceCollection列标注规则所属的数据模型,便于在流程中按数据源筛选加载。

计算引擎决定了表达式支持的语法。按 工作流计算节点文档的说明,目前支持的引擎有 Math.js 和 Formula.js,二者都内置了常用的函数和数据操作方法;另有一个"字符串模板"引擎,用于简单的字符串拼接(将表达式中的变量替换为对应值后返回拼接结果)。两个引擎的关键差异是数组下标访问:Math.js 的索引从1开始,Formula.js 从0开始,编写含数组下标的公式时需要特别注意。更多引擎细节可参考 计算引擎文档。

将业务数据与公式关联

创建好公式以后还需要将业务数据与公式进行关联。如果将每行业务数据直接关联到公式数据行会比较繁琐,通常的关联设计是引入一层类似"分类"的元数据表:

  1. 分类元数据表与公式表建立**多对一(或一对一)**关联——同一分类下的数据共享同一套公式;
  2. 再将业务数据与分类元数据建立多对一关联;
  3. 创建业务数据时只需指定特定的分类元数据,后续流程中即可通过这条关联路径找到对应的公式数据使用。

这种两级关联(业务数据 → 分类 → 公式)让"公式的切换"收敛到分类这一层:新增一种计算口径只需新增一行公式数据并建立新的分类,业务数据改挂新分类即可,无需修改流程配置。

流程中加载相应的数据

以数据表事件为例:创建一个工作流,当订单创建时触发,并需要预加载订单关联的商品数据和商品相关的表达式数据。这一步的意义在于,把后续动态计算所需的变量(订单明细、对应公式行)提前装入流程上下文,使动态计算节点执行时无需再发起额外查询,也保证公式中引用的变量在求值时一定存在。

加载完成后,流程中接入动态计算节点。该节点对应的服务端指令实现见 DynamicCalculation.ts#L14-L37:

export class DynamicCalculation extends Instruction { async run(node: FlowNodeModel, prevJob, processor: Processor) { let { engine = 'math.js', expression = '' } = node.config; let scope = processor.getScope(node.id); const parsed = parse(expression)(scope) ?? {}; engine = parsed.engine; expression = parsed.expression; scope = parse(node.config.scope ?? '')(scope) ?? {}; const evaluator = <Evaluator | undefined>evaluators.get(engine); try { const result = evaluator && expression ? evaluator(expression, scope) : null; return { result, status: JOB_STATUS.RESOLVED, }; } catch (e) { return { result: e.toString(), status: JOB_STATUS.ERROR, }; } } }

从这段源码可以梳理出动态计算节点的完整执行链路,它与"表达式表"方案的每个设计点一一对应:

  1. 引擎与表达式的来源是可动态解析的:节点配置中的engineexpression先作为字面量取默认值(engine默认为math.js,注意这与表达式表模板中formula.js的默认值不同,属于两处各自独立的默认),随后parse(expression)(scope)允许配置本身引用流程上下文变量——这正是"表达式存放在数据行、由流程按行加载"后依然能保持动态性的关键;
  2. 作用域(scope)的组装processor.getScope(node.id)获取当前节点可见的流程变量(前置节点结果、循环局部变量等),再叠加节点配置中scope的解析结果。从表达式表预加载的公式行、商品数据即通过这条通道进入作用域;
  3. 按引擎求值evaluators.get(engine)从求值器注册表中取出对应引擎(Math.js / Formula.js 等),对表达式求值并返回JOB_STATUS.RESOLVED与计算结果;
  4. 错误处理:若求值时变量不存在、类型不匹配或函数不存在,指令捕获异常并返回JOB_STATUS.ERROR,节点以出错状态提前终止,错误信息写入节点结果,便于在工作流执行记录中排查(该指令的行为另有测试用例 instruction.test.ts 覆盖)。

与静态"计算"节点的分工

在 NocoBase 工作流中还存在一个通用的计算(Calculation)节点,用于对固定写在节点配置里的表达式求值,同样支持 Math.js、Formula.js 与字符串模板引擎,其典型用例如用 Formula.js 的SUMPRODUCT函数计算订单总价。两者的分工可以概括为:

  • 计算节点:规则内联在工作流配置中,适合逻辑稳定、不随数据变化的计算;
  • 表达式表 + 动态计算指令:规则外置为数据行,按业务数据(经由分类等关联关系)逐行选择公式,适合"同一流程、多套计算口径"的运营化场景,例如不同商品类别使用不同的计价公式。

表达式表方案的本质,是把计算规则纳入 NocoBase 的数据模型管理(建表、录入、关联、查询),使公式的维护从"改流程配置"变为"维护数据",这是其与静态计算节点的核心差异。

小结

  • 表达式表通过expression集合模板创建,包含enginesourceCollectionexpression三个核心字段及审计字段,模板定义见 ExpressionCollectionTemplate.ts;
  • 每行数据是一条针对特定数据模型的计算规则,可逐行指定计算引擎,变量来自流程上下文中预加载的数据;
  • 业务数据建议经由分类元数据表与公式表两级关联,避免逐行直接关联;
  • 运行时由dynamic-calculation指令解析引擎与表达式、组装作用域并求值,源码见 DynamicCalculation.ts,指令与字段类型的注册见 Plugin.ts;
  • 使用前提注意:当前仓库中@nocobase/plugin-workflow-dynamic-calculation已标记废弃,落地前请确认目标版本中插件的可用状态,并对照 工作流计算节点与 计算引擎文档选择适合的求值方式。

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询