开源MIT!打造可插拔中国式 OA 工作流引擎 SailFlow

开源工作流别再硬堆 if‑else!我把 Slickflow 改造成可插拔中国式 OA 引擎 SailFlow

提示:项目还在持续迭代,存在破坏性变更,暂时不要直接上生产环境,架构基线已经成型,欢迎.NET 同行一起交流。

搞过 OA 审批流开发的朋友,大概率都踩过这种坑:

产品今天过来:这个节点要支持抢办;

过一周又改:要按组织单位映射选人;

再过几天:驳回之后单据要回送给打回人......

需求来一次,引擎内部就堆一堆if‑else。折腾几个版本之后,代码越堆越厚,后面谁都不敢碰,改需求如同拆炸弹。

作为.net老猿,折腾过许多工作流,总感觉不太趁手。一直想独立写,苦于没有精力。AI暴风时代,给我这种思想大于精力的给与了可能!那就开始吧,扬帆启航! sail-flow

基于开源项目 Slickflow,我做了二次深度改造,新项目命名 SailFlow,目标非常明确:插件式可插拔、多数据库适配,面向 .NET 6 / 8 /10,专门解决中国式 OA 审批的各类复杂场景。

开源仓库地址:

https://github.com/sailuosi/SailFlow

项目基于 MIT 协议,致敬上游 Slickflow,授权声明保留;数据层、数据结构、前端部分均已改造,后续独立演进,不再同步上游源码。gitee也有同名仓库。

SailFlow 到底是什么?

简单一句话:这是一套可以嵌入你自己业务系统的流程引擎内核,不绑定任何前端页面、菜单、办理工作台。

鉴权、业务菜单、办理页面全部留给宿主业务系统去实现,引擎内核只专心管好流程本身:

  • 流程启动、流转、驳回、加签撤回等流转逻辑
  • 审批人解析,节点放行判断
  • 业务校验、业务副作用、待办通知的挂载扩展

不用被迫使用整套成品 OA,拿来嵌入自己现有系统即可。

核心设计思想:一项能力,一个 UseXxx

借鉴ASP.NET Core 的能力启用思路,所有扩展能力全部显式插拔,不用就不引入对应依赖。

csharp

复制代码
var client = SailClient.CreateBuilder(configuration)
    .UseDatabase(...) //配置数据库
    .UseBizAssignees() //配置个性化待办人逻辑
    .UseBizRules()  //配置业务规则
    .UseBizMsg()  //配置消息体系
    .UseBizLocalize()  //配置语言
    .UseSailData()  //配置数据体系
    .UseFlowHook(...)  // 配置回调与钩子
    .Build();

只引用 NuGet 程序集,但不调用UseXxx方法,对应的扩展插槽就是空实现。

真正做到按需加载,不会仅仅引用引擎,就被动把 RabbitMQ、脚本引擎、规则引擎全部一股脑带入项目,拒绝隐形重型依赖。

三层架构分层:pure /ext/biz,重依赖不许污染内核

严格控制依赖方向,只允许上层依赖下层:

复制代码
Host 宿主业务应用
 └─ biz(业务门面、默认能力组合)
    └─ core/ext(可选组件:MQ、脚本、规则引擎、表单实现等,可替换)
       └─ core/pure(引擎骨架、流程契约,禁止重型NuGet包)
           └─ mooSQL
  • pure 层:纯粹流程语义、管道骨架,不引入重第三方组件
  • ext 层:MQ、Python 脚本、规则引擎等可选扩展,可替换可裁剪
  • biz 层:薄门面封装,只是转发调用,不写复杂内核逻辑

把过去 "MQ、邮件硬耦合引擎内核" 的历史债务全部清理干净。

契约下沉,实现上浮,内核保持干净,业务实现放到扩展层。

适配中国式 OA:不要硬套国外 Flowable 的概念

国内审批,最看重两件事:办理动词、办理模式,SailFlow 把二者做了分离,拒绝把复杂业务揉进一个枚举里面。

✅ 办理动词(内置码表)

通过、驳回、退回、加签、抄送、撤回、重发、跳转、关闭、转办......

其中重发 Resend 属于 SailFlow 特色能力,专门适配 "单据退回修改完成后,回送给原打回人复核" 这类国内高频场景,不是简单点一次同意。

✅ 办理模式(Leave,代表节点放行规则,不是页面按钮)

抢办、协办、组间抢办 / 协办、队长关卡等模式。

先定义清楚:节点要多少人办理完成,流程才可以往下走,再去定义页面按钮文案,而不是靠一个万能按钮吞掉全部业务语义。

退回逻辑同样做二维拆解:

  1. 退到哪里:上一跳、发起人、任意历史节点;
  2. 修改完成后如何发送:直接向下流转,还是返送给驳回人复核。

比起硬搬国外 BPMN 枚举,这套模型更贴合国内 OA 真实业务。

最头疼的待办人:双时刻管道,专治各种奇葩选人规则

OA 开发 80% 的坑,都出在 "该找谁审批" 这件事上。

SailFlow 把选人逻辑拆成两个时间点:

  1. Resolve(生成待办之前):解析出本节点需要哪些人来处理;
  2. Leave(节点推进之前):判断当前处理情况,节点是否允许放行离开。

配置统一采用{Type,Params}结构,按字符串 Type 注册,支持业务层覆盖重写,严禁通过修改内核、大量 if‑else 分支去实现业务选人逻辑。

内置已经支持大量解析策略:

固定人员、角色组、流程相对人、发起人自选、发送人自选、单位映射、岗位相对、业务回调、表达式、兜底策略等等。

内置放行模式:竞争抢办 Race、会签协作 Collaborate、分组 Group、队长 Captain 模式等。

几条工程上硬性约定:

  1. 组织分组 Group 和企业单位 Unit 正交区分,禁止拿 GroupId 冒充组织单位;
  2. 组织主数据全部保存在宿主系统,引擎只保留查询钩子;
  3. 选人配置缺失、解析为空办理人时:直接拒绝推进流程,返回明确错误码,不会静默把办理人改成发起人或者管理员,避免流程悄无声息异常;
  4. 待办办理人、消息通知、抄送三者完全三线分离,互不混淆。

一套管道扛住各类企业复杂组织选人需求。

事件体系:Gate / Hook / Notifier + Outbox,职责彻底分开

很多工作流引擎把校验、业务回调、消息通知全部混在一起,调试排查灾难。SailFlow 做了职责拆分:

  • Gate:流转前置校验,业务层可以直接拒绝本次流转;
  • Hook:流转完成之后执行业务副作用逻辑;
  • Notifier:专门处理待办消息通知旁路逻辑。

同时支持同步执行、Outbox 异步消息、失败重试、死信、指标埋点插槽。

每一类能力,对应一个UseXxx扩展,能力开关、数据表初始化、消息消费 Drain 全部内聚,不会在 Build 完成之后到处散落注册代码。

运维视角:分表、冷热归档不是后期补丁

很多流程引擎跑个几十万条实例之后,数据库性能直接崩盘。SailFlow 面向十万级年发起量做了设计,冷热分离可配置(默认关闭):

  • 业务热路径只访问热数据表;
  • 历史冷数据按年分表:*_hist_YYYY;
  • 流程轨迹、流程变量,支持按流程定义白名单开启分表;
  • 引擎日志输出 Sink、日志粒度完全可配置。

流程能跑起来只是及格;长期运行数据库不崩,才算真正落地。

SailFlow 适合谁?不适合谁?

✅ 适合场景

  1. .NET 技术栈团队,需要把流程引擎嵌入自有后台系统;
  2. 大量中国式审批,加签、抢办、退回返送等需求多;
  3. 审批人计算规则五花八门,不想每次改业务都动内核;
  4. 需要按需挂载 MQ、脚本、规则、AI 节点,追求轻量化可控。

❌ 暂时不适合

  1. 想要开箱即用完整 SaaS 审批产品,零代码直接上线;
  2. 无法接受迭代期破坏性变更,直接用于生产环境。

技术栈总览:.NET 多目标框架 + mooSQL 多数据库 + BPMN(sf 扩展标签)+ 插件管道模型

写在最后

现在开源工作流项目,不缺长长的功能清单。

真正稀缺的,是干净的扩展点。业务上来各种奇葩需求,你敢不敢不改引擎内核分支,只在外部扩展就搞定。

SailFlow 的设计赌注就在这里:

  • UseXxx 显式启用,拒绝隐形依赖;
  • pure 内核不背重型第三方包;
  • 待办人双时刻管道处理复杂选人;
  • 中国式办理动词与模式专门适配国内 OA;
  • Gate/Hook/Notifier/Outbox 事件职责分离。

MIT 开源,欢迎正在跟审批流死磕的小伙伴,前往仓库看能力基线,提 Issue、PR 一起打磨。

仓库地址:

https://github.com/sailuosi/SailFlow

仓库配套文档清单

表格

|---------------------|--------------------------------|
| 文档 | 用途 |
| README.md | 项目总览与能力一览 |
| 特性说明‑引擎能力基线.md | 命令、节点、插槽基准说明 |
| 特性说明‑待办人管道.md | 审批人解析专项文档 |
| 特性说明‑中国式 OA 审批要素.md | 办理动词与模式完整对照 |
| 架构设计‑项目依赖与分层.md | pure/ext/biz 分层详解 |
| 特性设计‑回调与事件.md | Gate/Hook/Notifier/Outbox 事件体系 |