ComponentContext 定义及常用字段说明
组件上下文(ComponentContext)是平台接口组件执行时的上下文对象,用于在组件之间传递数据和参数。
模型定义
/// <summary>
/// 组件上下文
/// </summary>
[Serializable]
public class ComponentContext
{
/// <summary>
/// 接口Id
/// </summary>
public string InterfaceId { get; set; }
/// <summary>
/// 通用Http请求参数,组件使用时,应该深度克隆一份,避免污染原始数据!!!
/// </summary>
public CommonRequestModel Request { get; set; }
/// <summary>
/// 额外And的条件(用于在条件链路上按需插入额外的查询条件)
/// </summary>
public DynamicFilter AndFilter { get; set; }
/// <summary>
/// Mou Filter配置(数据权限的扩展),与参数Filter是And关系
/// </summary>
public DynamicFilter MouFilter { get; set; }
/// <summary>
/// 条件覆盖(该参数赋值情况下,会覆盖其他所有条件,其他条件失效,主要用于触发器重新编辑条件)
/// </summary>
public DynamicFilter FilterOverride { get; set; }
/// <summary>
/// 字典类型参数(用于在脚本中传递参数)
/// </summary>
public Dictionary<string, string> DicParam { get; set; } = new();
/// <summary>
/// 弱类型通用参数(用于在脚本中传递参数)
/// </summary>
public object Param { get; set; }
/// <summary>
/// 当前组件的响应结果,可以透传到下一个组件,方便组件之间的数据传递
/// </summary>
public object CmpResult { get; set; }
/// <summary>
/// 最终响应结果
/// </summary>
public object Result { get; set; }
/// <summary>
/// 通用的整个链路参数模型,应该包含几乎所有有用的出入参数,以便在组件间维持一个标准的模型
/// 当为开始组件或者上一个组件被标记为输出到最终结果时,该模型会同时被赋值(以避免互相污染)
/// </summary>
public TransferModel TransferResult { get; set; }
}
C# 脚本中常用字段说明
| 字段 | 说明 |
|---|---|
| Request | 可以从中获取到前端请求的参数。Result.List 为 List<ObjectData> 类型,增删改查等 API 都会将参数传递到该属性中,可对照 Http 请求 Body 查看 |
| AndFilter | 额外 And 的条件(用于在条件链路上按需插入额外的查询条件)。常见于查询列表前在默认条件基础上额外拼接 And 条件 |
| MouFilter | Mou 权限相关 Filter,脚本中通常不需要修改此值 |
| FilterOverride | 覆盖所有条件(Mou 除外),通常用于自定义查询逻辑 |
| DicParam | 链路上下文的字典容器,Dictionary<string, string> 类型,可以将变量放在该容器中在多个组件之间传递。微服务请求时 DicParam 属性一定会传递到下游 |
| Param | 链路上下文的对象引用容器,object 类型,可以将变量以引用的形式在多个组件之间传递 |
| CmpResult | 上游组件的执行结果,定义类型为 object,数据处理类组件一般会以 List<ObjectData> 进行写入 |
| Result | 最终响应结果,脚本中通常不对该字段进行修改 |
| TransferResult | 脚本中通常不对该字段进行修改,该对象是通过微服务向下游传递的数据载体 |
系统内置变量说明
在接口组件提供了链路上下文的字典容器 context.DicParam,Dictionary<string, string> 类型,可以将变量放在该容器中在多个组件之间传递。系统内置了一些常用的上下文参数,在接口的不同组件中会动态赋值,方便后续直接取用。
| 变量 | 说明 |
|---|---|
| BizDataIds | 链路中当前操作的数据ID,批量操作时,该字段为多个ID通过英文逗号分隔的字符串。新增、编辑、删除、导入、查询等组件会默认赋值。在审批流接口选人场景,会自动将审批流实例数据对应的业务数据ID传入接口 |
| MetaObjectCode | 链路中当前操作的数据ID对应的对象编码 |
| MetaObjectId | 链路中当前操作的数据ID对应的对象ID |
| WorkflowLaunchUserId | 当前工作流发起人ID。工作流组件前可通过该ID动态设置工作流发起人。在工作流接口选人场景,会自动将审批流实例数据对应的审批发起人传入接口。如果工作流未设置发起人ID,则会默认取当前登录人员ID |
| WorkflowId | 当前工作流ID。在审批流接口选人场景,会自动将审批流实例数据对应的审批流ID传入接口。工作流组件执行后会自动赋值。如果需要在发起审批前动态控制使用哪个审批流,可以在流程组件前通过其他组件预先设置该值 |
| WorkflowNodeId | 当前工作流节点ID。在执行审批操作时,会自动将当前正在执行的节点ID传入接口 |
| WorkflowNodeType | 当前工作流节点类型(如 ApproveStart、ApproveNode、ApproveEnd 等)。在执行审批操作时,会自动将当前节点的类型传入接口 |
| WorkflowDataIds | 当前工作流实例数据ID。在审批流接口选人场景,会自动将审批流实例数据ID传入接口。工作流组件执行时会自动赋值。上游如果操作了多个业务数据,则该值为多个ID通过英文逗号分隔的字符串 |
| Action | 当前工作流操作动作。在执行审批操作时,会自动将当前执行的操作类型传入接口,方便在自定义接口中根据不同动作进行差异化处理。具体枚举值见下方 Action 枚举值详细说明 |
| NotifyUserIds | 在通知组件前动态赋值后,可向这些人员发送通知(建议判断非空后 Append 操作,避免覆盖前面已设置的值) |
Action 枚举值详细说明
Action 参数用于标识当前执行的工作流操作类型,开发者可以在自定义接口中根据不同的 Action 值实现差异化的业务逻辑。
| 枚举值 | 说明 | 触发场景 |
|---|---|---|
| UnKnown | 未知操作 | 默认值或无法识别的操作类型 |
| Launch | 发起审批 | 用户首次提交审批流程时触发。在流程开始节点执行,表示一个新的审批实例被创建并启动 |
| Agree | 同意/批准 | 审批人点击"同 意"按钮时触发。表示当前审批人批准了该节点的审批请求,流程将继续向下游流转 |
| Disagree | 不同意/拒绝 | 审批人点击"不同意"按钮时触发。表示当前审批人拒绝了该节点的审批请求,整个流程将被终止(状态变为 Rejected) |
| Return | 驳回/退回 | 审批人点击"驳回"按钮时触发。表示当前审批人将流程退回到上游某个节点(可配置是否允许选择目标节点),流程状态变为 Returned |
| Revoke | 撤回 | 发起人点击"撤回"按钮时触发。表示流程发起人主动撤回了正在进行的审批流程,流程状态变为 Revoked(需要节点配置允许撤回) |
使用示例:
public class ChameleonCSharpScript
{
public object Execute(ComponentContext context, IChameleonDbContext dbContext, ILogger logger)
{
// 获取当前操作动作
if (context.DicParam.TryGetValue("Action", out var action))
{
switch (action)
{
case "Agree":
// 同意时的业务逻辑
// 例如:记录审批日志、更新业务状态、触发后续流程等
logger.LogInformation("审批已被同意");
break;
case "Disagree":
// 不同意时的业务逻辑
// 例如:发送拒绝通知、回滚业务数据、记录拒绝原因等
logger.LogInformation("审批已被拒绝");
break;
case "Return":
// 驳回时的业务逻辑
// 例如:通知发起人被驳回、重置部分业务状态、记录退回信息等
var targetNodeId = context.Request.Result.List[0]["ReturnTargetNodeId"];
logger.LogInformation($"审批已被驳回到节点: {targetNodeId}");
break;
case "Revoke":
// 撤回时的业务逻辑
// 例如:清理中间状态数据、通知相关审批人、释放占用的资源等
logger.LogInformation("审批已被发起人撤回");
break;
case "Launch":
// 发起时的业务逻辑
// 例如:初始化业务数据、设置初始状态、发送启动通知等
logger.LogInformation("新审批流程已发起");
break;
default:
// 未知或未处理的操作
logger.LogWarning($"未知的操作类型: {action}");
break;
}
// 获取其他上下文信息
var nodeId = context.DicParam["WorkflowNodeId"];
var nodeType = context.DicParam["WorkflowNodeType"];
var workflowDataId = context.DicParam["WorkflowDataIds"];
logger.LogInformation($"节点ID: {nodeId}, 节点类型: {nodeType}, 实例ID: {workflowDataId}");
}
// 返回校验结果(对于 BeforeInterfaceId 接口特别有用)
// 可以返回一个包含校验结果的对象,由调用方决定是否继续执行
return new {
canProceed = true,
message = "校验通过"
};
}
}
典型应用场景:
-
BeforeInterfaceId 接口中的前置校验:
- 在
Agree动作执行前,校验业务数据是否符合审批条件 - 在
Return动作执行前,检查是否有权限驳回到指定节点 - 在
Revoke动作执行前,验证撤回时间窗口或业务约束
- 在
-
AfterInterfaceId 接口中的后置处理:
- 根据不同的 Action 执行不同的业务逻辑
Agree成功后:自动更新业务状态、触发关联流程Disagree后:发送拒绝通知、释放预留资源Return后:重置待办事项、通知目标节点审批人
-
条件性逻辑控制:
// 仅在同意和不同意时执行某些逻辑if (action == "Agree" || action == "Disagree"){// 统一的审批结果处理逻辑}// 驳回和撤回需要特殊处理if (action == "Return" || action == "Revoke"){// 需要清理或回滚的逻辑}
使用示例
public class ChameleonCSharpScript
{
public object Execute(ComponentContext context, IChameleonDbContext dbContext, ILogger logger)
{
// 获取当前操作的数据ID
var bizDataIds = context.DicParam["BizDataIds"];
// 获取当前对象编码
var metaObjectCode = context.DicParam["MetaObjectCode"];
// 获取工作流发起人ID
if (context.DicParam.TryGetValue("WorkflowLaunchUserId", out var launchUserId))
{
// 使用发起人ID进行业务处理
}
// 动态设置通知接收人
if (!context.DicParam.ContainsKey("NotifyUserIds"))
{
context.DicParam["NotifyUserIds"] = "user1,user2";
}
else
{
// 追加通知接收人,避免覆盖已设置的值
context.DicParam["NotifyUserIds"] += ",user3";
}
return null;
}
}