Skip to main content

C#脚本直接发起审批流

本文档介绍如何使用 C# 脚本通过 SDK 直接发起审批流,无需通过发起流程组件。

业务场景​

部分自定义场景下,需要通过代码控制审批流程的发起。在脚本组件或微服务中,可以方便地通过 SDK 提供的能力快速发起审批流,这种方式更加灵活和直观。

适用场景​

  • 列表行按钮触发审批
  • 定时任务自动发起审批
  • 条件判断后发起不同的审批流
  • 批量发起审批
  • 复杂业务逻辑控制审批发起

C#脚本示例​

以下是一个在列表行按钮触发审批的示例:

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Chameleon.Common;
using Chameleon.Common.Context;
using Chameleon.Common.Exceptions;
using Chameleon.Common.Models;
using Chameleon.Database;
using Chameleon.SDK;
using Chameleon.SDK.Models.Request.Workflow;

public class ChameleonCSharpScript
{
public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var obj = context.Request?.List?.FirstOrDefault();

if(obj == null)
return null;

var id = obj._id;

await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
// 数据对应的实体对象ID
MetaObjectId = "974e7421-7938-4890-b966-58efa9bc1123",
// 当前列表行请求数据ID
BizDataId = obj._id,
// 按这个审批流发起
WorkflowId = "06df2389-10cb-45de-8fcd-e84f49b4558f",
// 发起人(不填会自动取当前登陆人)
LaunchUserId = null,
});

return null;
}
}

参数说明​

WorkflowLaunchRequest 参数​

参数类型必填说明
MetaObjectIdstring是数据对应的实体对象ID
BizDataIdstring是业务数据ID
WorkflowIdstring是审批流ID
LaunchUserIdstring否发起人用户ID,不填则自动取当前登录用户

参数详解​

MetaObjectId(实体对象ID)​

  • 数据所在的实体对象ID
  • 可以在实体配置页面查看
  • 必须与 BizDataId 对应的实体一致

BizDataId(业务数据ID)​

  • 要发起审批的业务数据ID
  • 可以从 context.Request.List 中获取
  • 根据不同场景,数据来源可能不同

WorkflowId(审批流ID)​

  • 要发起的审批流ID
  • 可以在审批流配置页面查看
  • 审批流必须属于对应的实体对象

LaunchUserId(发起人ID)​

  • 可选参数,指定发起人
  • 不填写时,自动使用当前登录用户
  • 如果需要管理员代为发起,可以指定其他用户ID

关键点说明​

1. 异步方法调用​

SDK 的审批流 API 是异步方法,脚本方法签名需要改为 async Task<object> ExecuteAsync:

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
await sdk.WorkflowHelper.LaunchAsync(request);
return null;
}

2. 数据来源​

该脚本所在的接口在列表行功能按钮触发,因此可以从 context.Request.List 中获取到业务数据ID。其他场景需要根据情况决定业务数据ID的来源:

  • 列表行按钮:从 context.Request.List 获取
  • 表单提交:从 context.Request.List 获取表单数据
  • 定时任务:通过查询获取数据ID
  • 其他接口:根据具体业务逻辑获取

3. 返回值​

  • 返回 null 表示正常继续执行
  • 如需中断流程或返回错误,可返回错误消息字符串

扩展示例​

示例1:指定发起人​

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var obj = context.Request?.List?.FirstOrDefault();

if(obj == null)
return null;

// 指定发起人
var launchUserId = Convert.ToString(obj["Employee"]);

await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
MetaObjectId = "your-meta-object-id",
BizDataId = obj._id,
WorkflowId = "your-workflow-id",
LaunchUserId = launchUserId, // 指定发起人
});

return null;
}

示例2:条件判断发起不同审批流​

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var obj = context.Request?.List?.FirstOrDefault();

if(obj == null)
return null;

var type = Convert.ToString(obj["Type"]);
var workflowId = type switch
{
"A类" => "workflow-id-for-a",
"B类" => "workflow-id-for-b",
_ => "default-workflow-id"
};

await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
MetaObjectId = "your-meta-object-id",
BizDataId = obj._id,
WorkflowId = workflowId,
});

return null;
}

示例3:批量发起审批​

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var list = context.Request?.List;

if(list == null || !list.Any())
return null;

foreach(var obj in list)
{
await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
MetaObjectId = "your-meta-object-id",
BizDataId = obj._id,
WorkflowId = "your-workflow-id",
});
}

return null;
}

示例4:异步方法(推荐)​

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var obj = context.Request?.List?.FirstOrDefault();

if(obj == null)
return null;

await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
MetaObjectId = "your-meta-object-id",
BizDataId = obj._id,
WorkflowId = "your-workflow-id",
});

return null;
}

示例5:错误处理​

public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
var obj = context.Request?.List?.FirstOrDefault();

if(obj == null)
return "未找到数据";

try
{
await sdk.WorkflowHelper.LaunchAsync(new WorkflowLaunchRequest{
MetaObjectId = "your-meta-object-id",
BizDataId = obj._id,
WorkflowId = "your-workflow-id",
});

return null; // 成功
}
catch(Exception ex)
{
return $"发起审批失败:{ex.Message}";
}
}

与发起流程组件的区别​

SDK 直接发起方式​

优点:

  • 代码控制更灵活
  • 可以在脚本中进行复杂判断
  • 支持批量操作
  • 适合自定义业务逻辑

缺点:

  • 需要编写代码
  • 参数需要硬编码或动态获取

发起流程组件方式​

优点:

  • 可视化配置,无需编码
  • 参数配置直观
  • 适合标准场景

缺点:

  • 灵活性较低
  • 需要先通过脚本设置参数

注意事项​

  1. 权限要求:执行脚本的用户需要有发起审批的权限
  2. 审批流状态:确保审批流处于启用状态
  3. 数据状态:确保业务数据符合审批流的发起条件
  4. 重复发起:避免对同一数据重复发起审批
  5. 异步处理:推荐使用异步方法 ExecuteAsync 和 await 关键字
  6. 错误处理:建议添加异常捕获,提供友好的错误提示

常见问题​

Q: 如何获取审批流ID?​

A: 可以在审批流配置页面查看,或者通过 API 查询获取。

Q: 可以同时发起多个审批流吗?​

A: 可以,在脚本中多次调用 LaunchAsync 方法即可。

Q: 如何判断审批是否发起成功?​

A: 方法执行成功即表示发起成功,如果失败会抛出异常。

Q: 发起审批后如何获取审批实例ID?​

A: LaunchAsync 方法会返回审批实例信息,可以从返回值中获取。

Q: 可以在微服务中使用吗?​

A: 可以,在微服务中同样可以使用 SDK 的审批流 API。

相关文档​