条件分支节点
条件分支节点(ApproveCondition)用于审批流中的条件判断,根据业务数据字段值决定后续流转的分支。
概述
条件分支节点相当于审批流中的 if / else:组件同时对下游连出的分支求值,满足条件的分支继续执行。条件是针对审批流所属实体对象的字段值进行判断。
组件提供两种条件类型:实体数据条件(新版轻量条件,推荐)与实体数据条件(旧版)(拖拽式历史条件,已不再支持保存,需迁移)。
配置项
| 配置项 | 说明 |
|---|---|
| 条件类型 | 实体数据条件 / 实体数据条 件(旧版),必填,缺省为「实体数据条件」 |
条件类型取值
| 界面名称 | 值(ConditionType) | 说明 |
|---|---|---|
| 实体数据条件 | 1 | 轻量条件,按业务数据的字段值判断,缺省值 |
| 实体数据条件(旧版) | 0 | 历史条件,通过拖拽组件树配置,已不再支持保存 |
实体数据条件(ConditionType = 1)
在属性面板中直接增删条件行,每项由「字段 + 操作符 + 值」组成,支持「满足全部条件(And)」与「满足任一条件(Or)」两种组合方式:
- 选择字段,可选项来自审批流所属对象的字段列表
- 选择操作符,可选项随字段类型变化,例如数字字段支持
=、≠、>、≥、<、≤,文本字段支持=、≠、包含 - 填写比较值,控件随字段类型变化,例如日期使用日期选择器、布尔使用是/否下拉、用户或组织使用对应数据源下拉
每条条件行的取值方式可为「直接填值」或「Razor 表达式」。
实体数据条件(旧版)(ConditionType = 0)
历史条件通过拖拽组件树的方式配置,已不再支持保存:选中该类型时属性面板会提示迁移,并可点击「一键迁移」把已有旧版条件转换为新版条件。已发布的旧版条件仍按原有逻辑执行,不受影响,但再次保存发布前必须先完成迁移。
使用场景
- 按金额区间选择不同的审批路径
- 按业务状态值决定是否需要额外审批
- 按数据所属组织决定审批层级
下一步
属性明细
以下内容面向技术实现与 AI 检索,说明条件分支节点的节点元数据。
节点元数据
条件分支节点由 FlowCmpType.ApproveCondition 标识:
| 属性名 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|
type | string | 组件类型 | 固定为 "ApproveCondition" |
ConditionType | string | 条件类型 | "1"(缺省,实体数据条件)/ "0"(旧版) |
DynamicCondition | string(JSON) | 新版实体数据条件 | 条件配置 JSON,见 全局属性 |
Condition | string(JSON) | 旧版条件(拖拽树) | 旧版条件 JSON |
order | string | 同级排序 | 例:"3" |
元数据存储示例
{
"ID": "approve-cond1",
"type": "ApproveCondition",
"ConditionType": "1",
"DynamicCondition": "{\"Logic\":\"and\",\"Filters\":[{\"Field\":\"amount\",\"Operator\":\"gte\",\"Value\":\"1000\",\"ValueType\":\"Number\",\"ValueSetType\":\"Direct\"}]}",
"Condition": "",
"order": "3"
}
数据源
字段列表通过 GET /api/MetaField/GetAllListIncludeLookup(参数 metaObjectId 取审批流所属对象)获取。
服务端执行逻辑
条件分支节点由 ApproveConditionComponentManager 实现,继承 WorkflowComponentManagerBase,组件类型为 FlowComponentTypeEnum.ApproveCondition。
与运行期求值的 FlowCondition 不同,审批流中的条件分支在构建节点列表阶段(发起审批时)求值:_BuildAsync 对业务数据求值,命中则只把命中的下游分支构建进 WorkflowData.NodeItems;_ExecuteAsync 与 _NotifyAsync 均为空实现。因此分支结果由发起审批那一刻的业务数据一次性确定。
节点 meta 以 Dictionary<string, string> 存储,ConditionType 为字符串,DynamicCondition / Condition 为 JSON 字符串,服务端读取后反序列化。
执行时机与场景
| 时机 | 入口 | 说明 |
|---|---|---|
| 保存 / 发布校验 | _VerifyAsync | 仅 ConditionType = "1" 可校验;旧版条件直接抛错 |
| 发起审批(构建节点列表) | _BuildAsync | 在此按业务数据求值并完成分支路由 |
| 执行 / 通知 | _ExecuteAsync / _NotifyAsync | 空实现,直接返回上下文,不改变流程 |
输入参数(meta 键)
| meta 键 | 使用条件 | 含义 |
|---|---|---|
ConditionType | 必填 | 条件类型:"1" 实体数据条件;旧版走 default 分支被拒绝 |
DynamicCondition | ConditionType = "1" | 新版条件 JSON(DynamicFilter) |
Condition | 旧版 | 历史条件 JSON(List<WidgetItem>),当前不可保存 |
上下文入参:context.Result 必须为 WorkflowData;context.DicParam["MetaObjectId"] 提供审批流所属对象 Id。
执行步骤(_BuildAsync)
- 读取 meta 与
ConditionType;context.Result非WorkflowData时抛ApprovalNodeBuildFailed。 - 从
context.DicParam["MetaObjectId"]取对象 Id。 - 解析条件:
ConditionType = "1"时反序列化DynamicCondition为DynamicFilter,用WidgetConditionHelper.GetDynamicFilterFields取涉及的字段集合;否则反序列化Condition为List<WidgetItem>,取WidgetType == "FieldCondition"项中的字段。 - 加载对象(
GetMetaObjectByIdFromCacheAsync,同时写入DicParam的ChameleonMetaObjectId/ChameleonMetaObjectCode)与字段字典(GetMetaFieldsByMetaObjectIdFromCacheAsync)。 - 通过
chameleonDbContext.GetByIdAsync(metaObject.Code, flowData.BizDataId, allColumns)查询业务数据(缺失抛BusinessDataQueryFailed),再经dataSourceApp.TranslateLookupAsync关联 lookup 字段值。 - 计算命中结果:新版调用
WidgetConditionHelper.CalculateDynamicFilter,旧版调用CalculateCondition("And", ...)。 matched == true→ 调用BuildNextAsync构建下游分支;否则置context.CmpResult = false并返回。
分支路由规则
条件分支不区分「真 / 假」端口,仅按 matched 决定是否构建下游:
- 命中:只构建该条件节点连出的下游节点(按
order逐个)。 - 未命中:本节点不构建任何下游,由上层节点的
BuildNextAsync继续尝试同层其它分支(例如另一个配置相反条件的条件节点)。 - 若同层所有分支都未命中,
BuildNextAsync抛NotMetApprovalConditions,发起审批失败。
上下文写入与实例状态
| 目标 | 处理 |
|---|---|
context.CmpResult | 命中 true / 未命中 false |
context.DicParam | 写入 ChameleonMetaObjectId、ChameleonMetaObjectCode(加载对象时) |
flowData.Status / CurrentNode | 条件节点不修改实例状态 |
flowData.NodeItems | 命中时由其下游节点在 Build 阶段追加 |
校验规则(_VerifyAsync)
ConditionType | 校验内容 |
|---|---|
"1" | WidgetConditionHelper.VerifyDynamicFilterConfig(DynamicCondition) 校验条件 JSON 的字段与操作符非空 |
其他(含 "0") | 抛 LegacyConditionNotSupported,必须先在设计器中迁移为新版条件 |
校验通过后执行 VerifyNextAsync 递归校验下游节点。
异常与校验
| 场景 | 异常 / 提示 |
|---|---|
| 节点 meta 为空 | ConditionNodeMetaDataError |
| 旧版 / 非法条件类型 | LegacyConditionNotSupported |
| 条件 JSON 缺字段或操作符 | ConditionComponentConfigError(明细 ConditionComponentFieldOrOperatorEmpty) |
上下文结果非 WorkflowData | ApprovalNodeBuildFailed |
| 业务数据查询失败 | BusinessDataQueryFailed |
| 同层分支均未命中 | NotMetApprovalConditions |
权限与限制
- 分支在发起审批时按当时的业务数据一次性确定,流程进行中业务数据变化不会重新路由。
- 条件涉及的字段须存在于审批流所属对象中。
- 同一层级中,条件节点不能与审批节点混连(由基类
VerifyNextAsync约束)。
相关实现
| 项 | 位置 |
|---|---|
| 组件管理器 | ApproveConditionComponentManager(Components/Managers/WorkFlow/) |
| 条件求值 | WidgetConditionHelper.CalculateDynamicFilter / CalculateCondition |
| 分支构建 | WorkflowComponentManagerBase.BuildNextAsync |