跳到主要内容

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 条件
MouFilterMou 权限相关 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 = "校验通过"
};
}
}

典型应用场景:

  1. BeforeInterfaceId 接口中的前置校验:

    • 在 Agree 动作执行前,校验业务数据是否符合审批条件
    • 在 Return 动作执行前,检查是否有权限驳回到指定节点
    • 在 Revoke 动作执行前,验证撤回时间窗口或业务约束
  2. AfterInterfaceId 接口中的后置处理:

    • 根据不同的 Action 执行不同的业务逻辑
    • Agree 成功后:自动更新业务状态、触发关联流程
    • Disagree 后:发送拒绝通知、释放预留资源
    • Return 后:重置待办事项、通知目标节点审批人
  3. 条件性逻辑控制:

    // 仅在同意和不同意时执行某些逻辑
    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;
}
}

使用示例​

获取前端请求参数​

public class ChameleonCSharpScript
{
public object Execute(ComponentContext context, IChameleonDbContext dbContext, ILogger logger)
{
// 获取前端请求参数
var requestList = context.Request.Result.List;

foreach (var item in requestList)
{
var field1 = item["field1"];
var field2 = item["field2"];
}

return new { success = true };
}
}

添加额外查询条件​

public class ChameleonCSharpScript
{
public object Execute(ComponentContext context, IChameleonDbContext dbContext, ILogger logger)
{
// 在默认条件基础上额外拼接 And 条件
context.AndFilter = FilterBuilder.And(
FilterBuilder.Eq("status", "active"),
FilterBuilder.Gte("createdTime", DateTime.Today)
);

return null;
}
}

组件间数据传递​

public class ChameleonCSharpScript
{
public object Execute(ComponentContext context, IChameleonDbContext dbContext, ILogger logger)
{
// 通过 DicParam 传递字符串变量
context.DicParam["customKey"] = "customValue";

// 通过 Param 传递对象
context.Param = new { key1 = "value1", key2 = "value2" };

// 获取上游组件的执行结果
var upstreamResult = context.CmpResult as List<ObjectData>;

return null;
}
}

相关文档​