Skip to main content

条件分支组件

条件分支组件(FlowCondition)用于流程中的条件判断,根据条件结果决定后续是否继续执行下游分支。

概述​

条件分支相当于流程中的一道「闸门」:组件对自身配置的条件求值,条件成立时继续执行下游全部节点,条件不成立时当前分支就此终止,不产生任何输出。支持三种条件类型——实体数据条件、实体数据条件(旧版)与当前登录用户条件。

条件满足判断涉及「操作对象 + 条件项」与「数据匹配规则」,其中条件项由「字段 + 操作符 + 值」组成。

配置项​

配置项说明
条件类型实体数据条件 / 实体数据条件(旧版)/ 当前登录用户条件,必填

条件类型取值​

界面名称值(ConditionType)说明
实体数据条件2轻量条件,按业务数据的字段值判断,需指定操作对象
实体数据条件(旧版)0历史条件,通过拖拽组件树配置,已不再支持保存
当前登录用户条件1按当前登录用户的身份或角色判断

实体数据条件(ConditionType = 2)​

配置项说明
操作对象条件所依据的实体对象,必填
条件条件项列表,每项由「字段 + 操作符 + 值」组成
数据匹配规则全部数据满足:所有数据都要满足条件;任意一条数据满足:存在一条数据满足即可

条件项支持「满足全部条件(And)」与「满足任一条件(Or)」两种组合方式,可在条件区域右上角切换。条件项在属性面板中直接增删,不再弹出拖拽窗口:

  1. 选择字段,可选项来自操作对象的字段列表
  2. 选择操作符,可选项随字段类型变化,例如日期字段支持 =、≠、>、≥、<、≤,文本字段支持 =、≠、包含
  3. 填写比较值,控件随字段类型变化,例如日期使用日期选择器、布尔使用是/否下拉、用户或组织使用对应数据源下拉;文本字段绑定数据源时既可自由输入也可快捷选择

每条条件行的取值方式可为「直接填值」或「Razor 表达式」,表达式方式在条件行以「Razor」标签标识。

实体数据条件(旧版)(ConditionType = 0)​

历史条件通过拖拽组件树的方式配置,已不再支持保存:选中该类型时属性面板会提示迁移,并可点击「一键迁移到新版」把已有旧版条件转换为新版条件。已发布的旧版条件仍按原有逻辑执行,不受影响,但再次保存发布前必须先完成迁移。

当前登录用户条件(ConditionType = 1)​

配置项说明
用户条件类型具有某身份 / 具有某角色,必填
身份用户条件类型为「具有某身份」时配置,可多选
角色用户条件类型为「具有某角色」时配置,可多选

用户条件类型取值:

值(UserConditionType)说明
0具有某身份
1具有某角色

数据匹配规则取值​

界面名称值(DataMatchRule)说明
全部数据满足0所有数据都要满足条件
任意一条数据满足1存在一条数据满足即可

执行流程​

使用场景​

  • 按金额区间选择不同审批路径
  • 按状态值分流处理
  • 按当前登录用户的身份 / 角色分流

下一步​

属性明细​

以下内容面向技术实现与 AI 检索,说明条件分支组件的节点元数据。

节点元数据​

条件分支组件由 FlowCmpType.FlowCondition 标识:

属性名类型含义取值/存储值
typestring组件类型固定为 "FlowCondition"
ConditionTypestring条件类型"2"(缺省,实体数据条件)/ "0"(旧版)/ "1"(登录用户)
MetaObjectIdstring(GUID)条件依据的实体对象ConditionType = 0 / 2 使用
DynamicConditionstring(JSON)新版实体数据条件条件配置 JSON,见 全局属性
Conditionstring(JSON)旧版条件(拖拽树)旧版条件 JSON
DataMatchRulestring数据匹配规则"0"(缺省,全部满足)/ "1"(任一满足)
UserConditionTypestring用户条件类型"0"(缺省,身份)/ "1"(角色)
Profilesstring身份编码列表ConditionType = 1 且身份时使用,逗号分隔
Rolesstring角色编码列表ConditionType = 1 且角色时使用,逗号分隔
orderstring同级排序例:"1"

元数据存储示例​

{
"ID": "cond1",
"type": "FlowCondition",
"ConditionType": "2",
"MetaObjectId": "3f9c0b2e-2d3a-4e6f-9c11-0f7a5b8d2e10",
"DynamicCondition": "{\"Logic\":\"and\",\"Filters\":[{\"Field\":\"amount\",\"Operator\":\"gte\",\"Value\":\"1000\",\"ValueType\":\"Number\",\"ValueSetType\":\"Direct\"}]}",
"DataMatchRule": "0",
"order": "1"
}

数据源​

登录用户条件的身份 / 角色下拉分别通过 POST /api/DataSource/GetProfileDataSource、POST /api/DataSource/GetRolesDataSource 获取。

服务端执行逻辑​

条件分支由 FlowConditionComponentManager 实现,继承 TriggerComponentManagerBase(因此接口与触发器链路共用同一实现)。本节说明条件的求值、数据来源与分支路由规则。

元数据均为字符串

节点元数据以 Dictionary<string, string> 存储,ConditionType、DataMatchRule 等枚举值都是字符串;复杂条件以 JSON 字符串存入 Condition / DynamicCondition,服务端读取后再反序列化。

执行时机与场景​

时机说明
保存/发布校验_VerifyAsync 按条件类型校验必填项后,执行 VerifyNextAsync
流程执行到条件节点_ExecuteAsync 求值,命中则推进下游,未命中则终止当前分支

输入参数(meta 键)​

meta 键使用条件含义
ConditionType必填条件类型:"0" / "1" / "2"
MetaObjectId0 / 2条件依据的实体对象 id
Condition0旧版条件 JSON(List<WidgetItem>)
DynamicCondition2新版条件 JSON(DynamicFilter)
DataMatchRule0 / 2数据匹配规则:"0" 全部满足 / "1" 任一满足
UserConditionType1用户条件类型:"0" 身份 / "1" 角色
Profiles1 且 UserConditionType = 0身份编码,逗号分隔
Roles1 且 UserConditionType = 1角色编码,逗号分隔

校验规则(_VerifyAsync)​

ConditionType校验内容
0直接抛 LegacyConditionNotSupported,必须先在设计器中迁移为新版条件
2MetaObjectId 非空;通过 WidgetConditionHelper.VerifyDynamicFilterConfig(DynamicCondition) 校验条件 JSON 的字段与操作符非空
1 + UserConditionType = 0Profiles 非空
1 + UserConditionType = 1Roles 非空
其他抛 ConditionTypeInvalid

执行步骤​

_ExecuteAsync 先令 matched = true,再按类型求值:

  1. ConditionType = 2(轻量条件):反序列化 DynamicCondition 为 DynamicFilter;加载操作对象字段字典;逐条业务数据调用 WidgetConditionHelper.CalculateDynamicFilter(item, dynamicFilter, fields) 计算。
  2. ConditionType = 0(旧版条件):反序列化 Condition 为 List<WidgetItem>,经 WidgetConditionHelper.GetTiledItems 展平后取 WidgetType == "FieldCondition" 的项;逐条业务数据调用 WidgetConditionHelper.CalculateCondition("And", item, items, fields) 计算。
  3. ConditionType = 1(登录用户条件):身份走 userAccountService.VerifyUserHasProfilesAsync(UserId, Profiles.Split(',')),角色走 VerifyUserHasRolesAsync(UserId, Roles.Split(','))。

数据列表来源(0 / 2 类型)依次尝试:context.Request.List → context.CmpResult as List<ObjectData>;若最终为 null,直接 return context(不推进下游,等同未命中)。

匹配累加逻辑(0 / 2 类型一致):

DataMatchRule行为
"1"(任一满足)只要有一条数据命中即 matched = true 并 break;否则 matched = false
"0"(全部满足)逐条 matched &= 计算值;任一条不满足即置 false

注意:matched 初始为 true,且当列表为空时不会进入循环,因此空数据在两种规则下都会判定为命中。

分支路由规则​

条件求值结束后按 matched 决定走向,服务端不区分「真 / 假」端口:

  • Relations 解析时只保留边的 source.cell / target.cell,丢弃端口信息,因此引擎无法按「真 / 假」端口分流。
  • 命中时推进全部下游节点(按 order 降序逐个执行);未命中时该节点不产生任何下游执行。
  • 实现 if / else 语义时,需要在上游连出两个条件节点(一个配置正向条件、一个配置反向条件),或让不命中分支由另一个条件节点承接。

输出与上下文​

上下文属性条件分支的处理
Result / CmpResult不写入
DicParam类型 0 / 2 时会写入 MetaObjectId、MetaObjectCode(取自操作对象)
下游推进仅 matched == true 时调用 ExecuteNextAsync

异常与校验​

场景异常 / 提示
节点 meta 为空ConditionNodeMetaDataError
ConditionType = 0LegacyConditionNotSupported
操作对象未配置OperationObjectNotFound
条件配置缺字段或操作符ConditionComponentConfigError(明细:ConditionComponentFieldOrOperatorEmpty)
数据匹配规则未设置DataMatchRuleNotSet
身份 / 角色未配置IdentityConfigError / RoleConfigError
条件类型非法ConditionTypeInvalid