流程引擎四大模式及其通用操作机制研究
——基于 CCFlow 工作流引擎的设计与实现
作者:[待填写]
单位:[待填写]
通讯作者:[待填写]
收稿日期:[2026-06-12]
基金项目:[待填写]
中图分类号:TP311
文献标识码:A
文章编号:[CC2026-06-001]
目 录
- 引言
- 相关工作
- 系统总体架构与汽车类比模型
- 模式一:线形流程
- 模式二:同表单分合流
- 模式三:异表单分合流
- 模式四:父子流程
- 四大模式的覆盖性论证
- 节点通用操作
- 流程实例级操作
- 节点向下运动的核心算法:5×5 发送矩阵
- 多人处理规则
- 退回规则
- 案例研究与实验验证
- 结论与展望
参考文献
附录 A–H
致谢
插图清单
摘 要
企业流程自动化系统需要同时应对串行审批、并行会签、异构表单协同以及跨流程编排等多样化业务场景。本文以开源流程引擎 CCFlow(JFlow)为研究对象,提出并论证了流程引擎的四大模式——线形流程、同表单分合流、异表单分合流、父子流程——能够覆盖流程应用环境中的主要结构需求。在此基础上,本文进一步建立了"汽车控制系统"类比模型,将流程引擎、表单引擎与业务数据分别映射为汽车控制系统、车厢与货物,将发送、退回、移交、撤销、催办、加签等通用操作映射为驾驶行为。结合 BP.WF 后端核心模块与 Vue3/src/WF 前端实现,本文系统阐述了节点向下运动的 5×5 发送算法、多人处理规则(TodolistModel)、退回规则(ReturnRole)以及流程实例级操作(调整、回滚、逻辑删除、物理删除)的设计原理与实现机制。研究表明,CCFlow 以 RunModel 与 SubFlowModel 双维度模型、以 WorkID/FID/PWorkID 三元关联键、以统一发送引擎调度全部模式,在工程实践中具有良好的表达能力与可维护性。
关键词:工作流引擎;流程模式;分合流;父子流程;5×5 发送算法;CCFlow
Abstract
Enterprise workflow automation systems must address diverse scenarios including serial approval, parallel countersigning, heterogeneous form collaboration, and cross-process orchestration. This paper takes the open-source workflow engine CCFlow (JFlow) as the research object, proposes and demonstrates that the four major workflow patterns—linear workflow, same-form split-merge, different-form split-merge, and parent-child workflow—can cover the primary structural requirements of workflow application environments. Building on this foundation, we establish an “automobile control system” analogy model, mapping the workflow engine, form engine, and business data to the control system, carriage, and cargo respectively, and mapping common operations such as send, return, shift, undo, urge, and countersign to driving behaviors. Combined with the BP.WF backend core modules and the Vue3/src/WF frontend implementation, this paper systematically elaborates the design principles and implementation mechanisms of the 5×5 send algorithm for node downward movement, multi-person processing rules (TodolistModel), return rules (ReturnRole), and instance-level operations (adjust, rollback, logical delete, physical delete). The research shows that CCFlow, with its dual-dimensional model of RunModel and SubFlowModel, ternary association keys of WorkID/FID/PWorkID, and unified send engine scheduling all patterns, demonstrates good expressiveness and maintainability in engineering practice.
Keywords: Workflow Engine; Workflow Pattern; Split-Merge; Parent-Child Workflow; 5×5 Send Algorithm; CCFlow
1 引言
1.1 研究背景
随着企业数字化转型的深入,流程管理系统(BPM/Workflow)已从早期的 OA 审批工具,演进为连接组织、表单、数据与外部系统的业务编排中枢。一个成熟的流程引擎不仅需要支持"甲提交→乙审批→丙归档"这类简单串行场景,还必须应对以下复杂需求:
- 并行处理:同一单据需多人或部门同时处理后再汇总;
- 异构协同:不同岗位使用不同表单,完成后汇合到主流程;
- 跨流程编排:主业务触发子流程,子流程结束后反填主流程并驱动其继续运行;
- 丰富的运行时操作:发送、退回、移交、撤销、催办、加签、暂停、删除等;
- 实例级治理:对运行中或已完成的流程进行跳转、回滚、逻辑删除与物理删除。
国际上有 BPMN 2.0、Workflow Patterns(van der Aalst 等)等成熟理论,但其元素繁多、学习曲线陡峭,不利于企业业务人员快速建模。CCFlow(及其 Java 版本 JFlow)在国内政企、制造、金融等领域有大量落地实践,其提出的流程引擎四大模式——线形流程、同表单分合流、异表单分合流、父子流程——是一种面向工程落地的模式化抽象,具有重要的理论总结与论文化价值。
1.2 研究问题
本文围绕以下问题展开研究:
- RQ1:四大模式各自解决哪类流程结构问题?为何可以声称"涵盖流程应用环境的各个方面"?
- RQ2:四种模式在数据模型与运行时语义上如何区分与关联?
- RQ3:节点上的通用操作(发送、退回、移交等)能否由统一引擎支撑,而非各自独立实现?
- RQ4:节点向下运动的核心算法是什么?多人处理与退回规则如何与核心算法协同?
- RQ5:设计态(流程设计器)与运行态(待办处理)如何保持一致映射?
1.3 主要贡献
- 系统化定义流程引擎四大模式,给出每种模式的拓扑结构、适用场景、数据关联键及代码实现锚点;
- 提出"汽车控制系统"类比模型,统一阐释流程引擎、表单引擎、数据与通用操作之间的关系;
- 揭示 CCFlow 以
WorkNode.NodeSend_Send_5_5()为核心的 5×5 发送算法,说明其如何调度线形、分合流、子线程等全部运行模式; - 系统梳理
TodolistModel多人处理规则与ReturnRole退回规则,并说明其与发送、退回、移交、撤销算法的耦合方式; - 结合
Vue3/src/WF前端设计器与运行态页面,给出从设计到运行的端到端实现路径。
1.3.1 与既有理论的区别
| 维度 | Workflow Patterns / BPMN | 本文四大模式 |
|---|---|---|
| 受众 | 工作流研究人员、BPM 架构师 | 企业业务人员、实施顾问、二开工程师 |
| 粒度 | 43 种控制流模式 + 网关组合 | 4 种结构模式 + 统一操作集 |
| 数据视角 | 流程与数据分离(Data Object) | 表单驱动,PTable/FrmNode 与 RunModel 绑定 |
| 实现锚点 | 标准 XML 元素 | WF_Node.RunModel 字段 + NodeSend_Send_5_5() |
四大模式并非对 BPMN 的替代,而是对表单驱动型流程引擎在工程实践中的认知压缩(Cognitive Compression):将 Petri 网中的顺序、并行分支、同步合并、子网调用四类结构,与"同表/异表"数据维度、跨流程编排维度正交组合,形成可直接映射到数据库字段与 UI 图元的最小模式集。
1.4 论文结构
第 2 章介绍相关工作;第 3 章给出总体架构与汽车类比模型;第 4 章至第 7 章分别论述四大模式;第 8 章论述四大模式覆盖性;第 9 章论述节点通用操作;第 10 章论述流程实例级操作;第 11 章论述节点向下运动核心算法;第 12 章论述多人处理规则;第 13 章论述退回规则;第 14 章给出案例验证;第 15 章总结与展望。
2 相关工作
2.1 工作流理论与 Workflow Patterns
Petri 网、有限状态机为工作流的形式化基础提供了严格语义。van der Aalst 等提出的 Workflow Patterns 将流程控制结构归纳为 43 种模式,其中与本文四大模式密切相关的包括:
| Workflow Pattern | 模式编号 | 本文四大模式对应 |
|---|---|---|
| Sequence(顺序) | WCP-1 | 线形流程 |
| Parallel Split(并行分支) | WCP-2, WCP-4 | 同/异表单分合流之分流节点 |
| Synchronization(同步合并) | WCP-7, WCP-33 | 同/异表单分合流之合流节点 |
| Sub-Process | WCP-41 | 父子流程 |
BPMN 2.0 以 Sequence Flow、Parallel Gateway、Inclusive Gateway、Call Activity 等元素表达类似语义。与 BPMN 相比,CCFlow 的四大模式是面向业务人员的认知压缩:将网关、子流程、多实例活动等概念归纳为四种可组合的模式,降低建模门槛。
2.2 开源流程引擎对比
| 引擎 | 并行分支 | 子流程 | 特点 |
|---|---|---|---|
| Activiti/Camunda | Parallel Gateway | Call Activity | BPMN 标准,与标准元素一一对应 |
| Flowable | 同上 | 同上 | Activiti 分支,增强 REST 与 UI |
| CCFlow/JFlow | RunModel.FL/HL/FHL | SubFlowModel + PWorkID | 表单驱动,RunModel 显式标注,国内实践丰富 |
CCFlow 的差异化在于:将节点运行模式(RunModel)作为一等公民写入 WF_Node 表,并在发送引擎中以 5×5 矩阵统一调度,而非完全依赖 BPMN 解析器。
2.3 本文定位
本文并非提出全新的形式化工作流演算,而是对 CCFlow 工程实践中沉淀的"四大模式 + 通用操作 + 统一发送引擎"进行系统化理论总结与实现剖析,为流程引擎教学、选型与二次开发提供参考。
3 系统总体架构与汽车类比模型
3.1 分层架构
CCFlow 工作流子系统采用经典四层架构:
┌──────────────────────────────────────────────────────────────┐
│ 表现层 Vue3/src/WF │
│ FlowDesignerV2(设计器)/ MyFlow(运行态) │
├──────────────────────────────────────────────────────────────┤
│ 接口层 HttpHandler │
│ WF_MyFlow / WF_WorkOpt / WF_Admin_CCBPMDesigner │
├──────────────────────────────────────────────────────────────┤
│ 引擎层 BP.WF │
│ WorkNode / WorkReturn / WorkUnSend / ShiftWork │
│ WorkFlow / WorkReSend / Dev2Interface │
├──────────────────────────────────────────────────────────────┤
│ 模板层 BP.WF.Template │
│ Node / Direction / Cond / SFlow(子流程配置) │
├──────────────────────────────────────────────────────────────┤
│ 数据层 WF_Flow / WF_Node / WF_Direction │
│ WF_GenerWorkFlow / WF_GenerWorkerList / WF_Track │
└──────────────────────────────────────────────────────────────┘
[图1:CCFlow 工作流子系统分层架构图]
建议绘制:自上而下四层矩形框,标注各层核心类名与数据表名,用箭头表示调用方向。
3.2 汽车类比模型
为帮助业务人员与开发人员建立统一心智模型,本文提出如下类比:
| 汽车概念 | 流程引擎概念 | 代码/存储对应 | 说明 |
|---|---|---|---|
| 汽车控制系统 | 流程引擎 | WorkNode, WorkReturn, WorkUnSend | 控制车辆如何启动、前进、倒车、变道、停车 |
| 汽车车厢 | 表单引擎 | CCForm, MapData, FrmNode | 承载业务信息的容器,随流程节点切换而更换"车厢布局" |
| 货物 | 业务数据 | 业务主表(PTable)、从表(MapDtl) | 真正被运输和处理的对象 |
| 前进(踩油门) | 发送 | NodeSend(), ActionType.Forward | 流程向下运动 |
| 倒车 | 退回 | WorkReturn.DoIt(), ActionType.Return | 流程向上回退 |
| 换司机 | 移交 | ShiftWork.Node_Shift_ToEmp(), ActionType.Shift | 更换当前节点处理人 |
| 取消本次行程 | 撤销 | WorkUnSend.DoUnSend(), ActionType.UnSend | 撤销最近一次发送 |
| 鸣笛催办 | 催办 | Flow_DoPress(), ActionType.Press | 提醒待办人尽快处理 |
| 左拐/右拐 | 方向条件 | Direction, Cond, Func_GenerNextStepNodes() | 根据条件选择下一节点 |
| 中途换人协助 | 前加签/后加签 | Node_Askfor(), AskforHelpSta | 临时增加协助处理人 |
| 停车等待 | 挂起(暂停) | WorkFlow.DoHungup(), WFState.Hungup | 暂停流程运行 |
| 报废(标记) | 逻辑删除 | DoDeleteWorkFlowByFlag(), WFState.Delete | 标记删除,数据保留 |
| 报废(拆解) | 物理删除 | DoDeleteWorkFlowByReal() | 彻底清除全部关联数据 |
| 拖车到指定路口 | 调整 | Flow_ReSend(), ActionType.Adjust | 将运行中流程跳到指定节点/人员 |
| 行程记录回放 | 回滚 | DoRebackFlowData() | 已完成流程恢复到历史节点 |
[图2:汽车类比模型示意图]
建议绘制:一辆汽车的侧视图,标注"控制系统=流程引擎"“车厢=表单引擎”“货物=业务数据”,并用箭头引出各驾驶操作与流程操作的对应关系。
该类比的核心价值在于:流程引擎不负责"装什么货"(业务逻辑在表单与数据中),而负责"怎么运"(节点如何推进、如何回退、如何并行)。表单引擎与流程引擎解耦,使得同一流程引擎可驱动不同业务表单,同一表单也可被不同流程复用。
进一步地,方向条件对应汽车导航中的"路口选择":在 Func_GenerNextStepNodes() 中,引擎遍历当前节点的所有出边(WF_Direction),逐条评估 Cond 条件——表达式比较、SQL 查询、岗位/部门匹配等——决定"左拐"还是"右拐"。这与 BPMN 的 Exclusive Gateway / Inclusive Gateway 语义等价,但在 CCFlow 中无需额外网关节点,条件直接附着在连线上,降低了设计器图元的数量。
**阻塞模式(BlockModel)**可类比"前方施工禁行":在节点发送前,若 BlockModel ≠ None,引擎检查子线程是否全部完成(CurrNodeAll)、指定子流程是否到达某节点(SpecSubFlowNode)、或自定义 SQL/表达式是否返回阻塞信号,满足则禁止发送。这使父子流程、分合流场景下的"等待依赖"得以声明式配置。
3.3 核心数据模型
3.3.1 流程定义层
| 实体 | 表/类 | 关键字段 | 含义 |
|---|---|---|---|
| 流程 | WF_Flow / Flow | No, Name | 流程模板 |
| 节点 | WF_Node / Node | NodeID, RunModel, TodolistModel | 活动单元 |
| 方向 | WF_Direction / Direction | Node, ToNode | 节点连线 |
| 条件 | WF_Cond / Cond | 表达式/SQL | 方向生效条件 |
| 子流程配置 | WF_NodeSubFlow | SubFlowNo, SubFlowModel | 父子流程绑定 |
3.3.2 流程实例层
| 实体 | 表/类 | 关键字段 | 含义 |
|---|---|---|---|
| 工作实例 | WF_GenerWorkFlow | WorkID, FID, PWorkID, WFState | 一次流程运行 |
| 工作人员列表 | WF_GenerWorkerList | WorkID, FK_Node, FK_Emp, IsPass | 待办/已办 |
| 轨迹 | WF_Track | ActionType, NDFrom, NDTo | 操作审计日志 |
3.3.3 三种关联键
| 关联键 | 适用模式 | 含义 |
|---|---|---|
WorkID | 全部模式 | 工作实例主键,标识一次运行 |
FID | 分合流 | 子线程的 FID 指向干流程 WorkID |
PWorkID | 父子流程 | 子流程的 PWorkID 指向父流程 WorkID |
重要区分:FID 用于同一流程内的干/子线程关系;PWorkID 用于不同流程间的父/子调用关系。二者正交,可并存。
[图3:WorkID / FID / PWorkID 关系 ER 图]
建议绘制:三个实体框(干流程实例、子线程实例、子流程实例),标注关联键箭头。
3.4 节点运行模式枚举 RunModel
CCFlow 将节点的结构角色抽象为 RunModel 枚举(定义于 EnumLib.cs):
| 值 | 枚举名 | 中文标签 | 所属模式 |
|---|---|---|---|
| 0 | Ordinary | 线形 | 模式一 |
| 1 | HL | 合流 | 模式二/三 |
| 2 | FL | 分流 | 模式二/三 |
| 3 | FHL | 分合流 | 模式二/三 |
| 4 | SubThreadSameWorkID | 同表单子线程 | 模式二 |
| 5 | SubThreadUnSameWorkID | 异表单子线程 | 模式三 |
父子流程(模式四)不通过 RunModel 表达,而使用 NodeType.SubFlowNode 与 SubFlowModel 枚举。
4 模式一:线形流程
4.1 模式定义
线形流程是流程引擎中最基础的模式,指节点按有向图顺序(或条件分支)推进,RunModel = Ordinary(0),同一 WorkID 在节点间传递,FID = 0。
典型拓扑:
[开始节点] → [节点A] → [节点B] → [节点C] → [结束节点]
↘ [节点D] → [节点E] ↗ (条件分支仍属线形)
4.2 适用场景
- 请假、报销、用印等串行审批;
- 条件路由:根据表单字段值选择不同审批路径(通过
Direction+Cond实现,不改变RunModel); - 作为其他三种模式的"骨架",复杂流程通常以线形节点为主体,嵌入分合流或子流程节点。
4.3 运行时语义
- 处理人完成当前节点表单后,调用
WorkNode.NodeSend(); - 发送引擎执行
NodeSend_11(Node toND)——普通节点到普通节点; WorkID保持不变,业务主表OID = WorkID;Func_GenerNextStepNodes()根据方向条件计算下一节点集合;Func_GenerWorkerLists()按DeliveryWay(按部门、按角色、按表单字段等)计算接收人;- 在
WF_GenerWorkerList中插入下一节点待办记录; - 写轨迹
ActionType.Forward。
4.4 方向条件(左拐/右拐)
线形流程中的分支不依赖专用网关节点,而通过方向条件实现:
- 每条
Direction(WF_Direction)可配置一条或多条Cond(条件); - 条件支持:表达式(表单字段比较)、SQL、岗位、部门等;
Func_GenerNextStepNodes()遍历当前节点的所有出边,评估条件,返回满足条件的下一节点集合;- 若多条出边同时满足,可配置为"排他"或"并行"(后者需转入分合流模式)。
[图4:线形流程拓扑与方向条件示意图]
建议绘制:矩形节点 + 带标签的有向箭头(条件表达式标注在箭头上)。
4.5 前端实现
| 环节 | 文件/组件 | 说明 |
|---|---|---|
| 设计器形状 | Vue3/src/WF/Admin/FlowDesignerV2/shapes/index.ts | mode=0,矩形,标签"线性" |
| 节点属性 | Vue3/src/WF/Admin/AttrNode/NodeExt.ts | 配置 TodolistModel、退回规则等 |
| 方向条件 | NodeContextMenu → 方向条件配置 | 写入 WF_Cond |
| 运行态 | MyFlow.vue → MyFlow_Init → MyFlowGener.vue | 后端返回 PageName 动态加载 |
4.6 小结
线形流程是四大模式的基石,复杂度最低,却是理解发送引擎、多人规则、退回规则的入门路径。其 Ordinary → Ordinary 路径在 5×5 矩阵中对应 (0,0) 单元格。
5 模式二:同表单分合流
5.1 模式定义
同表单分合流指在**同一物理表(PTable)**上,由分流节点(RunModel.FL=2)启动多个子线程(RunModel.SubThreadSameWorkID=4),各子线程并行处理后,经合流节点(RunModel.HL=1)或分合流节点(RunModel.FHL=3)同步汇总,再继续主干流程。
典型拓扑:
[普通] → [分流 FL] ─┬→ [同表单子线程-甲] ─┐
├→ [同表单子线程-乙] ─┼→ [合流 HL] → [普通]
└→ [同表单子线程-丙] ─┘
5.2 适用场景
- 采购申请明细按行分派给不同采购员并行处理;
- 项目立项后多部门会签(共享同一申请单);
- 同一合同需法务、财务、业务三方并行审核后汇总。
5.3 数据模型
| 角色 | WorkID | FID | 物理表 |
|---|---|---|---|
| 干流程 | W0 | 0 | PTable(主表) |
| 子线程1 | W1 | W0 | PTable(同一表,OID=W1) |
| 子线程2 | W2 | W0 | PTable(同一表,OID=W2) |
| 合流后 | W0 | 0 | PTable(回到干流程 WorkID) |
子线程与干流程共享同一 PTable,通过不同的 OID(= 各自 WorkID)区分数据行。子线程的 FID 字段指向干流程 WorkID,建立从属关系。
5.4 核心算法
5.4.1 分流启动子线程
方法:WorkNode.NodeSend_24_SameSheet(Node toNode)
文件:CCFlow/Components/BP.WF/WF/WorkNode.cs
算法步骤:
- 根据
DeliveryWay(如ByDtlAsSubThreadEmps从明细表行确定人员)计算子线程接收人列表; - 为每个接收人生成独立
WorkID; - 设置子线程
wk.FID = 干流程 WorkID; - 复制分流节点表单数据到子线程(
Copy(this.HisWork)); - 在
WF_GenerWorkerList中为每个子线程插入待办; - 写轨迹
ActionType.ForwardFL。
5.4.2 子线程到达合流
方法:WorkNode.NodeSend_53_SameSheet_To_HeLiu(Node toNode)
算法步骤:
- 子线程处理完毕发送时,目标为合流节点;
- 更新当前子线程
GenerWorkerList.IsPass = 1(已办); - 在干流程
GenerWorkFlow.AtPara中维护ThreadCount(已到达合流点的子线程数); - 计算通过率:
passRate = numPassed / numAll × 100; - 当
passRate ≥ Node.PassRate(合流通过率,默认 100%)时:- 将合流节点
GenerWorkerList.IsPass置为 0(待办可见); - 干流程处理人可在合流节点继续操作;
- 将合流节点
- 执行合流汇总:
GenerHieLiuHuiZhongDtlData_2013()将子线程从表数据汇总到主干; - 写轨迹
ActionType.ForwardHL。
[图5:同表单分合流时序图]
建议绘制:参与者为干流程、分流节点、子线程×N、合流节点,按时间顺序标注 WorkID/FID 变化与 ThreadCount 递增。
5.4.3 合流通过率 PassRate
Node.PassRate 属性控制合流触发条件:
PassRate = 100:所有子线程完成后才触发合流(默认);PassRate = 50:过半子线程完成即可触发合流;- 适用于"多数决"类业务场景。
5.5 运行时管理
| 功能 | 属性/方法 | 说明 |
|---|---|---|
| 增加子线程 | ThreadIsCanAdd | 分流节点是否允许运行时增加子线程 |
| 删除子线程 | ThreadIsCanDel | 是否允许删除子线程 |
| 移交子线程 | ThreadIsCanShift | 是否允许移交子线程处理人 |
| 合流点补加 | ThreadIsCanAddOfHL | 合流节点是否允许补加子线程 |
| 子线程查询 | Dev2Interface.DB_GenerHLSubFlowDtl_TB() | 查询同表单合流子线程列表 |
5.6 前端实现
| 环节 | 文件 | 说明 |
|---|---|---|
| 设计器 | shapes/index.ts | 分流(2)、合流(1)、分合流(3)、同表单(4) 各有独立多边形 |
| 运行态 | MyFLDealThread.vue | 分合流专用处理页 |
| 子线程管理 | ThreadDtl.vue | 工具栏"子线程"弹窗 |
| 轨迹 | ActionType.ForwardFL(6) / ForwardHL(7) | 显示"分流前进"“合流前进” |
5.7 撤销与退回
- 撤销:
WorkUnSend.UnSend_FHL()针对分合流节点的专用撤销逻辑; - 退回:
WorkReturn中的分合流退回矩阵(如子线程退分流、合流退子线程等),详见第 13 章。
5.8 小结
同表单分合流解决了"同一单据、多人并行、数据共享"的核心需求,是政企会签类场景的主力模式。其关键在于 FID 关联与 PassRate 合流控制。
6 模式三:异表单分合流
6.1 模式定义
异表单分合流与同表单分合流共享分流(FL)、合流(HL)、分合流(FHL)节点类型,差异在于子线程节点使用 RunModel.SubThreadUnSameWorkID=5,每个子线程可绑定独立表单/物理表。
典型拓扑:
[普通] → [分流 FL] ─┬→ [异表单子线程-法务表单] ─┐
├→ [异表单子线程-财务表单] ─┼→ [合流 HL] → [普通]
└→ [异表单子线程-技术表单] ─┘
6.2 适用场景
- 项目立项后主流程表单不变,子线程分别走法务审查、财务评估、技术评审等独立表单;
- 采购主单不变,子线程分别填写供应商资质表、价格对比表、质量验收表;
- 任何需要"并行处理、异构表单、最终汇总"的场景。
6.3 与同表单的核心差异
| 维度 | 同表单 (RunModel=4) | 异表单 (RunModel=5) |
|---|---|---|
| 物理表 | 与干流程相同 PTable | 独立表单/表(FrmNodes, RefOneFrmTree) |
| WorkID 规则 | 每接收人一个 WorkID | 受 USSWorkIDRole 控制 |
| 数据复制 | Copy(HisWork) 同表复制 | GEEntityOID 独立插入 |
| 分流方法 | NodeSend_24_SameSheet() | NodeSend_24_UnSameSheet() |
| 合流方法 | NodeSend_53_SameSheet_To_HeLiu() | NodeSend_53_UnSameSheet_To_HeLiu() |
| 查询 API | DB_GenerHLSubFlowDtl_TB() | DB_GenerHLSubFlowDtl_YB() |
| 退回特性 | 标准退回 | 可启用 IsKillEtcThread(退回时终止其他子线程) |
[图6:同表单 vs 异表单分合流对比图]
建议绘制:左右两列对比图,标注数据表、WorkID、表单绑定差异。
6.4 USSWorkIDRole:异表单 WorkID 生成规则
NodeExt.cs 中定义:
| 值 | 含义 | 场景 |
|---|---|---|
| 0 | 仅生成一个 WorkID | 多人共享同一子线程实例(协作模式) |
| 1 | 按接收人生成 WorkID | 每人独立子线程实例(默认) |
6.5 核心算法
6.5.1 分流启动
方法:WorkNode.NodeSend_24_UnSameSheet(Nodes toNDs)
- 遍历目标子线程节点集合;
- 按
USSWorkIDRole决定 WorkID 生成策略; - 为每个子线程绑定独立表单,通过
FrmNodes配置表单与节点的关联; - 独立插入业务数据(
GEEntityOID); - 设置
wk.FID = 干流程 WorkID。
6.5.2 合流汇总
方法:WorkNode.NodeSend_53_UnSameSheet_To_HeLiu(Node nd)
- 合流逻辑与同表单类似(
ThreadCount+PassRate); - 额外执行字段级汇总:将各子线程表单字段值写入主干表单的合流汇总从表(
MapDtl.IsHLDtl = true)。
6.6 设计约束
代码中明确规定(WorkNode.cs):
- 分流节点不能同时启动同表单与异表单子线程;
- 分流节点不能同时启动多个同表单子线程(仅允许一个同表单子线程节点)。
这些约束保证了 5×5 发送矩阵的确定性。
6.7 前端实现
| 环节 | 文件 | 说明 |
|---|---|---|
| 设计器 | shapes/index.ts | mode=5/16,标签"异表单",梯形多边形 |
| 属性 | NodeExt.ts | USSWorkIDRole 配置 |
| 退回 | ReturnWork.vue | RunModel=4/5 时启用 IsKillEtcThread |
| 运行态 | MyFLDealThread.vue | 与同表单共用 |
6.8 小结
异表单分合流将流程引擎的表达能力从"同构并行"扩展到"异构并行",是复杂协同场景的关键模式。其与同表单的统一合流控制(PassRate + ThreadCount)体现了 5×5 算法的复用性。
7 模式四:父子流程
7.1 模式定义
父子流程实现跨流程实例的编排:父流程在某个节点触发子流程,子流程独立运行,结束后可反填父流程字段并驱动父流程继续。与分合流的本质区别在于:
| 维度 | 分合流 | 父子流程 |
|---|---|---|
| 关联键 | FID(同一 FlowNo 内) | PWorkID(不同 FlowNo 间) |
| 节点标识 | RunModel.FL/HL/SubThread* | NodeType.SubFlowNode |
| 配置表 | 无额外配置 | WF_NodeSubFlow |
| 生命周期 | 子线程随干流程结束而结束 | 子流程可独立运行、独立结束 |
7.2 子流程类型
FrmSubFlow.cs 定义:
| 类型 | 枚举值 | 触发方式 | 典型场景 |
|---|---|---|---|
| 手动子流程 | HandSubFlow = 0 | 用户在父流程表单点击启动 | 按需发起子审批 |
| 自动子流程 | AutoSubFlow = 1 | 节点发送时 CallAutoSubFlow() | 到达某节点自动创建 |
| 延续子流程 | YanXuFlow = 2 | 子流程结束后延续父流程 | 阶段性子任务 |
7.3 子流程模式
| 模式 | 枚举 | 含义 |
|---|---|---|
| 下级子流程 | SubLevel | 子流程挂到当前父 WorkID |
| 同级子流程 | SameLevel | 子流程挂到父流程的父级 |
7.4 典型拓扑
[父流程-节点A] → [父流程-节点B(含子流程配置)]
↓ 自动/手动启动
[子流程-开始] → [子流程-审批] → [子流程-结束]
↓ 子流程结束
反填父流程字段 → 驱动父流程到下一节点
[图7:父子流程生命周期状态图]
建议绘制:父流程状态机 + 子流程状态机,用虚线标注 PWorkID 关联与反填事件。
7.5 核心算法
7.5.1 建立父子关系
方法:Dev2Interface.SetParentInfo(subFlowNo, subFlowWorkID, parentWorkID, ...)
UPDATE WF_GenerWorkFlow
SET PFlowNo=..., PWorkID=..., PNodeID=..., PEmp=...
WHERE WorkID=子流程WorkID
7.5.2 手动启动
入口:WF_WorkOpt.SendSingleSubFlow()
SubLevel:Node_CreateBlankWork(subFlowNo, ..., parentWorkID, ...)+SetParentInfo()SameLevel:挂到gwf.PWorkID
7.5.3 自动启动
方法:WorkNode.CallAutoSubFlow()
- 按
InvokeTime(节点发送前/后)、条件表达式、SQL 数据源批量创建子流程实例; SubFlowHidTodolist可隐藏父流程待办(IsPass=100)。
7.5.4 子流程全部结束后的父流程处理
方法:WorkNodePlus.SubFlowOver_* 系列
规则 AllSubFlowOverRole:
| 规则 | 行为 |
|---|---|
None | 不驱动父流程 |
SendParentFlowToNextStep | 自动发送父流程到下一步 |
OverParentFlow | 结束父流程 |
字段反填:BackCopyRole 控制子流程字段向父流程的映射。
7.6 前端实现
| 环节 | 文件 | 说明 |
|---|---|---|
| 设计器 | subFlowNodes[0] | 六边形,NodeType.SubFlowNode=3 |
| 创建 | useVueFlowNode.ts → CreateSubFlowNode | |
| 配置向导 | GPN_NewSubFlow.ts | 手工/自动/延续/导航 |
| 实体 | SubFlowHand.ts, SubFlowAuto.ts, SubFlowYanXu.ts | |
| 运行态 | SubFlow.vue | 嵌入父流程表单 |
| 轨迹 | Track.vue | 聚合子流程实例卡片 |
| 动作 | ActionType.CallChildenFlow(9), StartChildenFlow(10) |
7.7 小结
父子流程解决了跨业务域流程编排问题,是四大模式中唯一涉及多个 FlowNo 的模式。PWorkID 关联键使其与分合流的 FID 完全正交。
8 四大模式的覆盖性论证
8.1 正交性与可组合性
四大模式并非互斥,一个完整企业流程通常是它们的组合:
[线形] → [分流] → [同表单子线程×3] → [合流] → [线形]
↓
[自动启动父子流程]
↓
[子流程:线形审批]
↓
[反填父流程] → [线形] → [结束]
8.2 需求覆盖表
| 企业需求 | 对应模式 | 说明 |
|---|---|---|
| 串行审批、条件分支 | 线形流程 | 通过方向条件实现分支 |
| 同一单据多人并行、会签 | 同表单分合流 | 共享 PTable |
| 并行子任务、异构表单 | 异表单分合流 | 独立表单绑定 |
| 跨业务域编排、主从单据 | 父子流程 | PWorkID 关联 |
| 复杂监管(并行+子流程+汇总) | 多模式组合 | 四大模式正交组合 |
8.3 "涵盖流程应用环境各个方面"的论证
从结构维度看,任意流程图均可分解为以下基本元素:
- 顺序执行 → 线形流程;
- 并行分支与同步合并(同构数据) → 同表单分合流;
- 并行分支与同步合并(异构数据) → 异表单分合流;
- 流程间调用 → 父子流程。
从操作维度看,第 9–13 章论述的通用操作(发送、退回、移交等)在所有模式下均可用统一引擎调度。因此,四大模式 + 通用操作构成了流程应用环境的最小完备集。
8.4 局限性
- 分流节点不能混启同表单与异表单子线程;
- 极端复杂编排(事件子流程、循环子流程)需结合脚本/服务任务扩展;
- 与 BPMN 完整语义并非一一对应,偏向表单驱动型场景。
[图8:四大模式组合示例图]
建议绘制:一个完整企业流程图,用不同颜色标注四种模式所在区段。
9 节点通用操作
流程引擎在每个节点上提供一组通用操作,类比汽车驾驶行为(见 3.2 节)。本节结合 BP.WF 源码,逐一阐述各操作的触发条件、算法与轨迹记录。
9.1 操作总览
| 操作 | 汽车类比 | 核心类/方法 | ActionType | WFState 变化 |
|---|---|---|---|---|
| 发送(前进) | 踩油门 | WorkNode.NodeSend() | Forward(1) | Runing |
| 退回(后退) | 倒车 | WorkReturn.DoIt() | Return(2) | ReturnSta(5) |
| 移交(换司机) | 换司机 | ShiftWork.Node_Shift_ToEmp() | Shift(3) | Shift(6) |
| 撤销(取消任务) | 取消行程 | WorkUnSend.DoUnSend() | UnSend(5) | 恢复上一状态 |
| 催办(鸣笛) | 鸣笛 | Dev2Interface.Flow_DoPress() | Press(18) | 不变 |
| 前加签 | 临时乘客 | Dev2Interface.Node_Askfor() | AskforHelp(24) | Askfor(8) |
| 后加签 | 临时乘客 | Node_Askfor() + AskforHelpSta | ForwardAskfor(25) | AskForReplay(10) |
| 会签(前加签扩展) | 多位乘客 | Node_HuiQian_AddEmps() | HuiQian(30) | HuiQianing |
| 删除 | 报废 | WorkFlow.DoDeleteWorkFlowByFlag/Real() | DeleteFlowByFlag(19) | Delete(7) |
| 挂起(暂停) | 停车 | WorkFlow.DoHungup() | Hungup(15) | Hungup(4) |
[图9:节点通用操作与汽车类比对照图]
建议绘制:汽车仪表盘图标,每个图标旁标注对应操作名称与 ActionType。
9.2 发送(前进)
9.2.1 入口与调用链
前端 MyFlowGener.vue
→ HttpHandler WF_WorkOpt
→ Dev2Interface.Node_SendWork()
→ WorkNode.NodeSend()
→ NodeSend_Send_5_5()
9.2.2 三阶段处理
NodeSend() 方法体分为三大部分(WorkNode.cs 代码注释明确,约第 7613 行):
-
发送前检查(第 1 部分):
- 流程是否已结束(
IsOver)或逻辑删除(WFState.Delete); - 当前用户是否有处理权限(
Flow_IsCanDoCurrentWork); - Guest 节点身份校验;
- 会签状态检查(会签中是否允许发送);
- 合流子线程是否全部完成;
- 阻塞模式(
BlockModel)检查; - 必填项校验;
- 触发
EventListNode.SendWhen事件。
- 流程是否已结束(
-
5×5 核心算法(第 2 部分):详见第 11 章。
-
发送后处理(第 3 部分):
- 更新
GenerWorkFlow状态; - 写
WF_Track轨迹; - 多人规则处理(队列/协作/抢办);
- 会签完成判断;
- 抄送(CC);
- 子流程自动启动(
CallAutoSubFlow); - DTS 数据同步;
- 消息推送;
- 触发
EventListNode.SendSuccess事件。
- 更新
9.3 退回(后退)
9.3.1 入口
前端 ReturnWork.vue
→ WF_WorkOpt.DoReturnWork()
→ Dev2Interface.Node_ReturnWork()
→ WorkReturn.DoIt()
9.3.2 算法概要
- 若
returnToNodeID == 0,调用DB_GenerWillReturnNodes(workid)按ReturnRole计算可退节点列表; DoIt()分支:- 跨流程退回 →
ReturnToParentFlow(); - 同节点队列模式 →
DoOrderReturn(); - 目标为协作/组长且
TeamReturnRole==1→DoOrderReturn(); - 否则按 当前 RunModel × 目标 RunModel 矩阵调用
ExeReturn1_1()、ExeReturn2_4()等;
- 跨流程退回 →
- 清理中间节点
GenerWorkerList、审核轨迹; IsBackTrack控制是否保留中间节点业务数据;- 更新
WFState = ReturnSta,写ActionType.Return或ReturnAndBackWay(201)。
详见第 13 章退回规则。
9.4 移交(换司机)
9.4.1 入口
前端 Shift.vue
→ WF_WorkOpt.Shift_Save()
→ Dev2Interface.Node_Shift()
→ ShiftWork.Node_Shift_ToEmp()
9.4.2 算法
- 校验:流程未完成、被移交人不在当前待办;
- 按
TodolistModel分支:- 协作/队列/组长模式:删除移交人
GenerWorkerList,插入被移交人记录,重算 SDT(应完成时间); - 抢办模式:直接 UPDATE 或重建
GenerWorkerList;
- 协作/队列/组长模式:删除移交人
- 设置
gwf.WFState = WFState.Shift; - 更新
TodoEmps字段; - 写
ActionType.Shift,触发EventListNode.ShitAfter与消息推送。
撤销移交:ShiftWork.DoUnShift() → ActionType.UnShift(4)。
9.5 撤销(取消任务)
9.5.1 入口
前端在途列表
→ WF.Runing_UnSend()
→ Dev2Interface.Flow_DoUnSend()
→ WorkUnSend.DoUnSend()
9.5.2 算法
- 校验
CancelRole:若为None则禁止撤销; - 开始节点禁止撤销;
- 对方已读/已办时禁止(受
CancelDisWhenRead控制); - 会签状态:默认禁止(
IsEnableUnSendWhenHuiQian可放开); - 查
GenerWorkerList中IsPass=1的记录确定cancelToNodeID; - 按节点类型(普通/分流/合流/子流程/游离态)分别调用
DoUnSendIt()、DoUnSendFeiLiu()、DoUnSendHeiLiu_Main()等; - 恢复上一节点待办,删除后续节点数据;
- 写
ActionType.UnSend; - 若 Track 存在
Return/ReturnAndBackWay,撤销后恢复WFState.ReturnSta。
9.5.3 撤销规则 CancelRole
| 值 | 含义 |
|---|---|
OnlyNextStep | 仅允许撤销到下一步 |
None | 禁止撤销 |
NextStepAndStartNode | 可撤销到下一步和开始节点 |
SpecNodes | 可撤销到指定节点 |
9.6 催办(鸣笛)
9.6.1 入口
前端 Press.vue
→ WF_WorkOpt.Press()
→ Dev2Interface.Flow_DoPress()
9.6.2 算法
- 校验流程未完成且非开始节点;
- 查当前节点
GenerWorkerList(IsPass=0)获取待办人; - 按日写入
PressWork催办记录表(防重复:WorkID_UserNo_ToEmp_Date); Port_SendMsg(..., SMSMsgType.DoPress)发送消息(站内信/短信/微信等);- 写
ActionType.Press; - 可选递归催办子流程待办人。
会签主持人催办:HuiQian_Press() 专门催办会签中的待办人。
9.7 前加签与后加签
CCFlow 将"加签"与"会签"分为两套机制:
9.7.1 加签(Askfor)——单人请求协助
| 概念 | 说明 |
|---|---|
| 前加签 | 处理人先请他人协助,协助完成后由自己继续发送 |
| 后加签 | 处理人先发送,加签人协助后流程才到下一步 |
入口:WF_WorkOpt.Askfor() → Dev2Interface.Node_Askfor()
算法:
- 设
WFState.Askfor; - 在
GenerWorkerList为被加签人插入待办,PassInt存储加签模式; - 被加签人处理完毕后
DealAskForState()根据AskforHelpSta:AfterDealSend(5):加签后直接发送 → 继续NodeSend到下一步(后加签语义);AfterDealSendByWorker(6):加签后由发起人发送 →WFState.AskForReplay,待办回到发起人(前加签语义);
Node_AskforReply():加签人回复后触发发送或返回。
9.7.2 会签(HuiQian)——多人同节点会签
| 方法 | 功能 |
|---|---|
Node_HuiQian_Init() | 初始化会签界面数据 |
Node_HuiQian_AddEmps() | 增加会签人(IsPass=-1) |
Node_HuiQian_AddLeader() | 激活组长(IsPass=-1→0) |
Node_HuiQianDone() | 发起会签,通知会签人 |
Node_HuiQian_Delete() | 删除会签人 |
会签完成判断在 NodeSend 发送后处理中,依据 HuiQianRole、HuiQianLeaderRole、TeamLeaderConfirmRole 决定是否全员完成。
[图10:前加签与后加签流程对比图]
建议绘制:两种加签模式的泳道图,标注 AskforHelpSta 分支。
9.8 删除
9.8.1 逻辑删除
方法:WorkFlow.DoDeleteWorkFlowByFlag()
- 设
WFState = Delete; - 删除
GenerWorkerList(待办不可见); - 保留
WF_Track轨迹和业务主表数据; - 可恢复:
DoUnDeleteWorkFlowByFlag()。
9.8.2 物理删除
方法:WorkFlow.DoDeleteWorkFlowByReal()
- 删除
WF_Track、GERpt、MapDtl、各节点表单数据; - 删除
WF_GenerWorkFlow、WF_GenerWorkerList、WF_CCList; - 不可恢复。
9.8.3 写日志删除
方法:WorkFlow.DoDeleteWorkFlowByWriteLog()
- 先插入
WorkFlowDeleteLog; - 再调用
DoDeleteWorkFlowByReal()。
9.8.4 删除权限 DelWorkFlowRole
| 值 | 含义 |
|---|---|
None | 禁止删除 |
DeleteByFlag | 仅逻辑删除 |
DeleteAndWriteToLog | 写日志后物理删除 |
DeleteReal | 直接物理删除 |
ByUser | 由用户选择删除方式 |
9.9 挂起(暂停)
CCFlow 中"暂停"对应 挂起(Hungup)。
方法:WorkFlow.DoHungup()
- 设
WFState = Hungup; - 在
AtPara记录挂起人、方式(HungupWay:永久/指定日期)、审批人; - 通知除开始节点外的当前待办人;
- 审批人
HungupWorkAgree()解除挂起,或HungupWorkReject()拒绝; - 写
ActionType.Hungup(15)/UnHungup(16)。
入口:WF_WorkOpt.Hungup_Save() → Dev2Interface.Node_HungupWork()。
10 流程实例级操作
节点通用操作作用于当前节点,而流程实例级操作作用于整个流程实例,通常由管理员执行。
10.1 调整(ReSend)
定义:将运行中的流程实例跳转到指定节点、指定人员,使其在该节点产生待办。
入口:Dev2Interface.Flow_ReSend(workid, toNodeID, toEmps, note, model)
算法:
- 校验:流程未完成、非子线程节点、非"退回并原路返回"状态;
type=1(向前跳过):Flow_ReSendBySkip()——当前待办转已办、强制结束子流程、重建目标节点待办;- 否则:
WorkReSend.DoIt()按 RunModel 矩阵调整(类似退回的逆操作); - 写
ActionType.Adjust(31)。
应用场景:流程发错节点、需要管理员干预跳转、跳过某些审批环节。
[图11:流程调整前后状态对比图]
建议绘制:调整前节点高亮 vs 调整后节点高亮的流程图。
10.2 回滚(Rollback)
定义:将已完成的流程实例恢复到指定历史节点,使其重新进入运行状态。
入口:WF_WorkOpt.Rollback_Done() → FlowExt.DoRebackFlowData()
算法:
- 从
WF_Track轨迹重建GenerWorkFlow和GenerWorkerList; - 恢复到指定节点,
WFState = ReturnSta; - 清理完成后的冗余数据;
- 逻辑删除恢复(
DoUnDeleteWorkFlowByFlag)也调用此接口。
与退回的区别:
| 维度 | 退回 | 回滚 |
|---|---|---|
| 执行人 | 当前节点处理人 | 管理员 |
| 流程状态 | 运行中 | 已完成 |
| 权限 | 节点 ReturnRole | 流程 RollbackPower |
回滚权限 RollbackPower(Flow.cs):
| 值 | 含义 |
|---|---|
| 0 | 管理员 |
| 1 | 流程参与人 |
| 2 | 指定节点处理人 |
| 3 | 指定角色 |
| 4 | 指定人员 |
10.3 逻辑删除与物理删除
已在 9.8 节论述。实例级删除通过 WF_WorkOpt.DeleteFlowInstance_DoDelete() 入口,按 DelWorkFlowRole 分支调用不同删除方法。
10.4 小结
| 操作 | 适用状态 | 核心方法 | 可逆性 |
|---|---|---|---|
| 调整 | 运行中 | Flow_ReSend() | 可再次调整 |
| 回滚 | 已完成 | DoRebackFlowData() | 可再次回滚 |
| 逻辑删除 | 任意 | DoDeleteWorkFlowByFlag() | 可恢复 |
| 物理删除 | 任意 | DoDeleteWorkFlowByReal() | 不可恢复 |
11 节点向下运动的核心算法:5×5 发送矩阵
11.1 算法背景
CCFlow 的发送引擎经历了多次演进。2012 年升级的 NodeSend_Send_5_5() 方法将发送逻辑统一为 5×5 矩阵:当前节点 RunModel(行)× 目标节点 RunModel(列),每个单元格对应一个专用发送方法。这一设计避免了为每种模式编写独立引擎,保证了撤销、退回、轨迹的一致性。
11.2 矩阵结构
CCFlow 源码注释将发送逻辑称为"5×5 算法"(WorkNode.NodeSend(),2012-11-11 厦门升级),意指当前节点 5 类运行角色 × 目标节点 5 类运行角色的笛卡尔调度。其中子线程的"同表单/异表单"是同一行内的分支,而非独立行。RunModel 枚举共 6 个值(0–5),在 NodeSend_Send_5_5() 的 switch 中合并为 5 个 case 分支。
目标节点 RunModel
Ord(0) HL(1) FL(2) FHL(3) Same(4) UnSame(5)
当前 Ordinary(0) [11] [11] [11] [11] 禁止 禁止
节点 HL(1) [31] [31] [31] [31] 禁止 禁止
RunM FL(2) [11] [11] [11] [11] [24_S] [24_U]
odel FHL(3) [11] [11] 禁止 [11] [24_S] [24_U]
Same(4) 禁止 [53_S] 禁止 [53_S] [11] 禁止
UnSame(5) 禁止 [53_U] 禁止 [53_U] 禁止 [11]
注:[11] = NodeSend_11();[24_S] = NodeSend_24_SameSheet();[24_U] = NodeSend_24_UnSameSheet();[31] = NodeSend_31();[53_S/U] = 合流方法。空白/禁止格在代码中 throw Exception 提示流程设计错误。
核心源码结构(WorkNode.NodeSend_Send_5_5(),CCFlow/Components/BP.WF/WF/WorkNode.cs):
switch (this.HisNode.HisRunModel)
{
case RunModel.Ordinary: // 行1:普通节点
switch (toND.HisRunModel) {
case RunModel.Ordinary: this.NodeSend_11(toND); break;
case RunModel.SubThreadSameWorkID:
case RunModel.SubThreadUnSameWorkID:
throw new Exception("普通节点不能连接子线程节点");
}
break;
case RunModel.FL: // 行2:分流节点
switch (toND2.HisRunModel) {
case RunModel.SubThreadSameWorkID:
NodeSend_24_SameSheet(toND2); break;
case RunModel.SubThreadUnSameWorkID:
NodeSend_24_UnSameSheet(toNDs); break;
}
break;
case RunModel.HL: // 行3:合流节点
this.NodeSend_31(toND3); break;
case RunModel.SubThreadSameWorkID: // 行4/5:子线程
case RunModel.SubThreadUnSameWorkID:
if (toND5.HisRunModel == RunModel.HL)
NodeSend_53_SameSheet_To_HeLiu(toND5); // 或 UnSameSheet 版本
break;
}
设计约束(源码强制校验,保证矩阵确定性):
- 分流节点不能同时启动同表单与异表单子线程(
workflow_error_4); - 分流节点不能同时启动多个同表单子线程(
workflow_error_5); - 普通节点不能直接连接子线程节点(须经分流节点);
- 合流节点不能连接子线程节点。
[图12:5×5 发送矩阵示意图]
建议绘制:6×6 矩阵表格,有效单元格绿色高亮、禁止单元格灰色标注 Exception,并在图旁附上述 switch 伪代码。
11.3 关键单元格详解
| 单元格 | 方法 | 场景 |
|---|---|---|
| (0,0) | NodeSend_11() | 线形 → 线形(最常用) |
| (0,4) | NodeSend_24_SameSheet() | 线形 → 同表单子线程(经分流) |
| (2,4) | NodeSend_24_SameSheet() | 分流 → 同表单子线程 |
| (2,5) | NodeSend_24_UnSameSheet() | 分流 → 异表单子线程 |
| (4,1) | NodeSend_53_SameSheet_To_HeLiu() | 同表单子线程 → 合流 |
| (5,1) | NodeSend_53_UnSameSheet_To_HeLiu() | 异表单子线程 → 合流 |
| (1,0) | NodeSend_31() | 合流 → 线形(合流后继续) |
| (3,*) | 分合流行 | 分合流节点可再次分流 |
11.4 算法执行流程
NodeSend(jumpToNode, jumpToEmp)
│
├─ 第1部分:发送前检查
│ ├─ 权限校验
│ ├─ 状态校验(已结束/已删除/会签中)
│ ├─ 阻塞模式检查
│ └─ SendWhen 事件
│
├─ 第2部分:5×5 核心算法
│ ├─ Func_GenerNextStepNodes() // 计算下一节点
│ ├─ 遍历下一节点集合
│ │ └─ switch(当前RunModel)
│ │ └─ switch(目标RunModel)
│ │ └─ 调用对应 NodeSend_XY() 方法
│ └─ 子流程自动启动 CallAutoSubFlow()
│
└─ 第3部分:发送后处理
├─ 更新 GenerWorkFlow
├─ 写 Track
├─ 多人规则(队列/协作/抢办)
├─ 会签完成判断
├─ 抄送 CC
├─ DTS 同步
├─ 消息推送
└─ SendSuccess 事件
11.5 下一节点计算
方法:Func_GenerNextStepNodes()
- 查询当前节点的所有出边(
WF_Direction); - 对每条出边评估条件(
Cond):- 表达式条件:解析表单字段值,执行比较;
- SQL 条件:执行 SQL 查询,返回行数 > 0 则满足;
- 岗位/部门条件:判断当前处理人是否匹配;
- 返回满足条件的下一节点集合;
- 若仅一个下一节点,直接发送;若多个,根据配置决定排他或并行。
11.6 接收人计算
方法:Func_GenerWorkerLists(Node toNode)
- 读取目标节点的
DeliveryWay(接收人规则); - 按规则计算人员集合(
ByStation、ByDept、BySQL、BySelected、ByDtlAsSubThreadEmps等 20+ 种); - 过滤无效人员;
- 返回
(EmpNo, EmpName)列表。
11.7 算法优势
- 统一性:全部模式走同一入口,撤销/退回/轨迹逻辑一致;
- 可扩展性:新增 RunModel 只需扩展矩阵行列;
- 可测试性:每个单元格可独立单元测试;
- 可维护性:避免 if-else 堆叠,逻辑清晰。
12 多人处理规则
12.1 TodolistModel 枚举
当同一节点有多个接收人时,TodolistModel 决定他们如何协作:
| 值 | 枚举名 | 中文 | 行为 | 汽车类比 |
|---|---|---|---|---|
| 0 | QiangBan | 抢办 | 谁先处理谁生效,其他人待办自动消除 | 多人抢开一辆车 |
| 1 | Teamup | 协作 | 所有人都要处理,最后一人发送到下一步 | 多人轮流驾驶 |
| 2 | Order | 队列 | 按顺序处理,最后一人发送到下一步 | 排队驾驶 |
| 3 | Sharing | 共享 | 需申请后才能处理 | 需拿钥匙才能开 |
| 4 | TeamupGroupLeader | 协作组长 | 组员协作 + 组长确认 | 车队队长最后验收 |
定义位置:EnumLib.cs 第 640 行;节点属性 Node.TodolistModel(WF/Node.cs 第 2633 行)。
[图13:多人处理规则示意图]
建议绘制:五种模式的泳道图,标注待办生成与消除时机。
12.2 抢办模式(QiangBan)
行为:
- 为所有接收人各插入一条
GenerWorkerList(IsPass=0); - 任一人发送时,将其余人
IsPass置为 1(自动已办); - 流程向下运动。
适用场景:值班审批、客服处理——谁有空谁处理。
12.3 协作模式(Teamup)
行为:
- 为所有接收人各插入一条
GenerWorkerList(IsPass=0); - 每人发送时仅将自己的
IsPass置为 1; - 当最后一人发送时,流程才向下运动;
- 发送后处理中判断
IsAllPassed()。
适用场景:多部门会签、联合审批——所有人都必须发表意见。
12.4 队列模式(Order)
行为:
- 为所有接收人按顺序插入
GenerWorkerList,仅第一人IsPass=0,其余IsPass=-1(未到); - 当前人发送后,下一人
IsPass从 -1 变为 0; DealOradeNode()方法管理队列推进;- 最后一人发送时流程向下运动。
适用场景:逐级审批——必须按职级顺序处理。
12.5 共享模式(Sharing)
行为:
- 所有接收人可见待办,但需先"申请"才能获得处理权;
- 申请后其他人待办消除;
- 处理完毕发送。
适用场景:任务池、工单抢单。
12.6 协作组长模式(TeamupGroupLeader)
行为:
- 组员按协作模式处理;
- 组长通过
TeamLeaderConfirmRole计算; - 组长最后确认后流程向下运动。
12.7 会签机制(HuiQian)
会签是协作模式的扩展,通过 HuiQianRole 控制:
| HuiQianRole | 含义 |
|---|---|
Teamup(1) | 协作会签 |
TeamupGroupLeader(4) | 组长会签 |
组长会签规则 HuiQianLeaderRole:
| 值 | 含义 |
|---|---|
OnlyOne | 仅一个组长 |
LastOneMain | 最后一个组长为主持人 |
EveryOneMain | 每人都可以是主持人 |
12.8 多人规则在操作中的体现
| 操作 | 抢办 | 协作 | 队列 |
|---|---|---|---|
| 发送 | 一人发送即可 | 最后一人发送 | 按序发送 |
| 退回 | 标准退回 | TeamReturnRole 控制 | DoOrderReturn() |
| 移交 | UPDATE 单人 | 替换 GenerWorkerList | 替换当前队列项 |
| 撤销 | 标准撤销 | 协作节点特殊处理 | 恢复队列状态 |
13 退回规则
13.1 ReturnRole 枚举
每个节点可配置 ReturnRole,决定处理人可以退回到哪些历史节点:
| 值 | 枚举名 | 中文 | 行为 |
|---|---|---|---|
| 0 | CanNotReturn | 不能退回 | 该节点禁止退回操作 |
| 1 | ReturnPreviousNode | 仅上一节点 | 只能退回到直接前驱节点 |
| 2 | ReturnAnyNodes | 任意历史节点 | 可退回到任何已处理过的节点(默认) |
| 3 | ReturnSpecifiedNodes | 指定节点 | 仅可退回到配置的节点列表 |
| 4 | ReturnStartNode | 退到开始节点 | 只能退回到流程开始节点 |
| 5 | ByReturnLine | 按退回线 | 由流程图上标注的退回方向决定 |
定义位置:EnumLib.cs 第 1250 行;计算可退节点:Dev2Interface.DB_GenerWillReturnNodes(workid)。
13.2 可退节点计算
方法:DB_GenerWillReturnNodes(workid)
- 读取当前节点的
ReturnRole; - 按规则查询
WF_GenerWorkerList历史记录; - 分流/合流节点特殊处理:直接查
GenerWorkerList而非按ReturnRole; - 返回可退节点列表供前端展示。
[图14:退回规则与可退节点计算流程图]
建议绘制:ReturnRole 分支判断的流程图。
13.3 退回执行矩阵
WorkReturn.DoIt() 按 当前 RunModel × 目标 RunModel 矩阵调用执行方法:
| 方法 | 场景 |
|---|---|
ExeReturn1_1() | 线形 → 线形 |
ExeReturn2_4() | 分流 → 同表单子线程 |
ExeReturn3_2() | 合流 → 分流 |
ExeReturn3_4() | 合流 → 同表单子线程 |
ExeReturn5_2() | 同表单子线程 → 分流 |
DoItOfKillEtcThread() | 子线程退分流且杀死其他子线程 |
ReturnToParentFlow() | 跨流程退回到父流程 |
DoOrderReturn() | 队列/协作模式专用退回 |
13.4 退回并原路返回
ActionType:ReturnAndBackWay(201)
行为:
- 退回到目标节点后,处理人重新处理;
- 处理完毕后,流程自动按原路径返回到退回前的节点;
- 在
GenerWorkFlow.AtPara中记录返回路径; - 适用于"退回到发起人修改后直接回到当前审批人"的场景。
13.5 分合流退回特殊规则
| 场景 | 规则 |
|---|---|
| 子线程退分流 | 可选 IsKillEtcThread:是否终止其他子线程 |
| 合流退子线程 | 需清理 ThreadCount |
| 分流节点 | 不按 ReturnRole 算,直接查 GenerWorkerList |
| 协作节点 | TeamReturnRole==1 时走 DoOrderReturn() |
13.6 退回与撤销的协同
- 若流程经退回后发送,再撤销:撤销会恢复到
WFState.ReturnSta; - 若 Track 存在
ReturnAndBackWay,撤销后保留原路返回标记; - 退回后的业务数据处理受
IsBackTrack控制。
13.7 前端实现
| 环节 | 文件 | 说明 |
|---|---|---|
| 退回页面 | ReturnWork.vue | 展示可退节点列表 |
| 初始化 | WF_WorkOpt.Return_Init() | 调用 DB_GenerWillReturnNodes |
| 执行 | WF_WorkOpt.DoReturnWork() | 调用 Node_ReturnWork |
| 异表单 | ReturnWork.vue | RunModel=4/5 时显示 IsKillEtcThread 选项 |
14 案例研究与实验验证
14.1 案例一:采购申请(同表单分合流)
业务描述:采购员提交采购申请,系统按明细表行自动分派给各采购专员并行询价,全部完成后汇总到采购主管处合流审批。
配置要点:
| 节点 | RunModel | 关键属性 |
|---|---|---|
| 开始 | Ordinary | — |
| 采购员提交 | Ordinary | — |
| 分流 | FL(2) | DeliveryWay=ByDtlAsSubThreadEmps |
| 专员询价×N | SubThreadSameWorkID(4) | 共享主表 |
| 主管合流 | HL(1) | PassRate=100 |
| 结束 | Ordinary | — |
验证步骤:
- 提交含 3 行明细的采购申请;
- 验证生成 3 个子线程,各专员待办正确;
- 专员 1、2 完成,合流未触发;
- 专员 3 完成,合流触发,主管待办出现;
- 查
WF_Track轨迹含ForwardFL和ForwardHL。
[图15:采购申请案例流程图]
建议绘制:案例流程图 + 运行截图(待办列表、轨迹)。
14.2 案例二:项目立项(异表单分合流)
业务描述:项目经理提交立项申请(主表单),系统自动分流到法务、财务、技术三方,各方填写独立评审表单,完成后合流汇总到总经理审批。
配置要点:
| 节点 | RunModel | 关键属性 |
|---|---|---|
| 开始 | Ordinary | — |
| 项目经理提交 | Ordinary | 主表单 Frm_Project |
| 分流 | FL(2) | 出边 3 条,分别连向 3 个子线程 |
| 法务评审 | SubThreadUnSameWorkID(5) | 绑定 Frm_LegalReview |
| 财务评审 | SubThreadUnSameWorkID(5) | 绑定 Frm_FinanceReview |
| 技术评审 | SubThreadUnSameWorkID(5) | 绑定 Frm_TechReview |
| 总经理合流 | HL(1) | PassRate=100,合流从表 IsHLDtl=true |
| 结束 | Ordinary | — |
数据流:
- 干流程
WorkID=W0,FID=0,主表Frm_Project的OID=W0; - 分流后生成 3 个子线程:
W1(FID=W0)、W2(FID=W0)、W3(FID=W0),各自绑定不同物理表; - 法务填写
Frm_LegalReview,财务填写Frm_FinanceReview,互不干扰; - 三方完成后
ThreadCount递增至 3,触发合流; NodeSend_53_UnSameSheet_To_HeLiu()将各子表单关键字段汇总到主表合流从表;- 总经理在主表单看到三方评审摘要后审批。
验证步骤:
- 提交立项申请,验证 3 个子线程待办分别出现在法务/财务/技术人员待办列表;
- 验证各子线程打开的是不同表单(非同一 PTable);
- 仅完成 2 个子线程时,总经理无待办;
- 第 3 个子线程完成后,总经理待办出现;
- 查
WF_Track含 3 条SubThreadForward与 1 条ForwardHL; - 测试退回:子线程退分流时勾选
IsKillEtcThread,验证其余子线程被终止。
[图16:项目立项异表单分合流案例图]
建议绘制:主表单 + 三个独立子表单 + 合流汇总从表的 ER 关系图,并附运行态截图。
14.3 案例三:合同审批调用法务子流程(父子流程)
业务描述:合同审批流程到达"法务审核"节点时自动启动法务子流程;子流程独立走完法务审批链后,反填合同审批单字段并自动驱动父流程到下一节点。
配置要点:
| 配置项 | 值 | 说明 |
|---|---|---|
| 父流程节点 | NodeType.SubFlowNode | 六边形子流程节点 |
| 子流程类型 | AutoSubFlow(1) | 节点发送时自动触发 |
| 子流程模式 | SubLevel | PWorkID 指向父 WorkID |
| 启动时机 | InvokeTime = 发送后 | CallAutoSubFlow() |
| 全部结束规则 | SendParentFlowToNextStep | 子流程全结束后自动发送父流程 |
| 字段反填 | BackCopyRole | 子流程"法务意见"→父流程"法务审核意见" |
| 待办隐藏 | SubFlowHidTodolist=true | 父节点 IsPass=80,待办不可见 |
生命周期:
- 业务员在父流程"合同审批"节点点击发送;
NodeSend_Send_5_5()正常发送后,触发CallAutoSubFlow();- 创建子流程实例
W_sub,PWorkID=W_parent,PFlowNo=合同审批,PNodeID=法务审核节点; - 父流程当前处理人待办设为不可见(
IsPass=80); - 法务人员在子流程中完成多级审批;
SubFlowOver_SendParentFlowToNextStep()检测全部子流程结束;- 执行字段反填,恢复父流程待办,自动
NodeSend到下一节点; - 轨迹记录
ActionType.StartChildenFlow(10)与CallChildenFlow(9)。
验证步骤:
- 父流程发送到法务节点,验证子流程自动创建且
PWorkID正确; - 验证父流程发起人在此期间待办不可见(在途可查进度);
- 子流程完成后,验证父流程字段被反填;
- 验证父流程自动流转到下一节点(如"总经理审批");
- 测试催办:
Flow_DoPress(workID, msg, isPressSubFlow=true)可递归催办子流程待办人。
[图17:合同审批父子流程案例图]
建议绘制:父流程 + 子流程双泳道图,标注 PWorkID、IsPass=80 隐藏区间、反填箭头。
14.4 案例四:请假审批(线形流程 + 多人规则组合)
业务描述:员工提交请假申请,部门经理与 HR 按队列模式逐级审批,最后由分管领导协作会签后归档。全程为线形流程,无分合流。
配置要点:
| 节点 | RunModel | TodolistModel | 说明 |
|---|---|---|---|
| 开始 | Ordinary | — | 员工填写 |
| 部门经理 | Ordinary | Order(2) | 若多人则按职级队列 |
| HR 审批 | Ordinary | QiangBan(0) | 多人抢办,谁先处理谁生效 |
| 分管领导 | Ordinary | Teamup(1) | 协作会签,全员完成后发送 |
| 结束 | Ordinary | — | 归档 |
验证要点:
- 队列节点验证
IsPass=-1(未到)与顺序激活; - 抢办节点验证一人发送后他人待办自动消除;
- 协作节点验证最后一人发送才触发
NodeSend_11(); - 退回测试:
ReturnRole=ReturnPreviousNode,部门经理退回后员工修改再提交。
[图18:请假审批线形流程案例图]
建议绘制:简单线性流程图,标注各节点 TodolistModel 图标。
14.5 通用操作验证矩阵
| 操作 | 线形 | 同表单分合流 | 异表单分合流 | 父子流程 |
|---|---|---|---|---|
| 发送 | ✓ | ✓ | ✓ | ✓ |
| 退回 | ✓ | ✓ | ✓ | ✓ |
| 移交 | ✓ | ✓ | ✓ | ✓ |
| 撤销 | ✓ | ✓ | ✓ | ✓ |
| 催办 | ✓ | ✓ | ✓ | ✓ |
| 加签 | ✓ | ✓ | ✓ | — |
| 挂起 | ✓ | ✓ | ✓ | ✓ |
| 调整 | ✓ | ✓ | ✓ | — |
| 回滚 | ✓ | ✓ | ✓ | ✓ |
15 结论与展望
15.1 主要结论
-
四大模式构成最小完备集:线形流程、同表单分合流、异表单分合流、父子流程分别从顺序执行、同构并行、异构并行、跨流程编排四个维度覆盖了流程应用环境的主要结构需求,且可正交组合。
-
统一发送引擎保证一致性:CCFlow 以
RunModel枚举和 5×5 发送矩阵统一调度全部模式,使得发送、退回、撤销、轨迹、待办查询共用一套基础设施。 -
三元关联键语义清晰:
WorkID标识实例,FID承载分合流关系,PWorkID承载父子流程关系,三者正交。 -
汽车类比模型降低认知门槛:将流程引擎、表单引擎、业务数据分别类比为控制系统、车厢、货物,将通用操作类比为驾驶行为。
-
通用操作与多人/退回规则协同:发送、退回、移交等操作均考虑
TodolistModel与ReturnRole,保证复杂场景下行为一致。 -
前后端一致映射:Vue3 设计器通过
RunModel形状模板实现设计态可视化,运行态由后端PageName动态路由。
15.2 未来工作
- 模式自动识别与流程检查增强;
- BPMN 2.0 导入导出映射;
- 基于 AI 的流程模式推荐;
- 5×5 发送矩阵的形式化验证;
- 微服务架构下的分布式扩展。
致 谢
[待填写:感谢导师、项目组、CCFlow 开源社区及资助单位等。]
参考文献
[1] van der Aalst W M P, ter Hofstede A H M, Kiepuszewski B, et al. Workflow Patterns[J]. Distributed and Parallel Databases, 2003, 14(1): 5-51.
[2] OMG. BPMN 2.0 Specification[S]. Object Management Group, 2011.
[3] 柴晓伟, 周朋. CCFlow/JFlow 工作流引擎技术白皮书[R]. 济南驰骋信息技术有限公司, 2020.
[4] Ellis C A, Maltzahn C. The ε-Challenges on the Workflow Way[J]. Concurrency: Practice and Experience, 1997, 9(10): 859-872.
[5] Reichert M, Weber B. Enabling Flexibility in Process-Aware Information Systems[J]. Data & Knowledge Engineering, 2012, 76: 13-47.
[6] 范玉顺, 王刚, 高展. 工作流管理技术基础[M]. 北京: 清华大学出版社, 2001.
[7] Russell N, ter Hofstede A H M, Edmond D, et al. Workflow Resource Patterns[J]. BETA Working Paper Series, 2004.
[8] 周朋. BP.WF 工作流引擎核心源码解析[M]. 济南: 驰骋技术, 2019.
[9] Dumas M, La Rosa M, Mendling J, et al. Fundamentals of Business Process Management[M]. 2nd ed. Berlin: Springer, 2018.
[10] ISO/IEC 19510:2013. Information technology — Object Management Group Business Process Model and Notation[S]. 2013.
附录 A RunModel 完整枚举
| 值 | 枚举名 | 中文标签 | 所属模式 |
|---|---|---|---|
| 0 | Ordinary | 线形 | 模式一 |
| 1 | HL | 合流 | 模式二/三 |
| 2 | FL | 分流 | 模式二/三 |
| 3 | FHL | 分合流 | 模式二/三 |
| 4 | SubThreadSameWorkID | 同表单子线程 | 模式二 |
| 5 | SubThreadUnSameWorkID | 异表单子线程 | 模式三 |
附录 B 5×5 发送矩阵方法对照表
| 当前\目标 | Ordinary(0) | HL(1) | FL(2) | FHL(3) | Same(4) | UnSame(5) |
|---|---|---|---|---|---|---|
| Ordinary(0) | NodeSend_11 | NodeSend_11 | NodeSend_11 | NodeSend_11 | 禁止 | 禁止 |
| HL(1) | NodeSend_31 | NodeSend_31 | NodeSend_31 | NodeSend_31 | 禁止 | 禁止 |
| FL(2) | NodeSend_11 | NodeSend_11 | NodeSend_11 | NodeSend_11 | NodeSend_24_SameSheet | NodeSend_24_UnSameSheet |
| FHL(3) | NodeSend_11 | NodeSend_11 | 禁止 | NodeSend_11 | NodeSend_24_SameSheet | NodeSend_24_UnSameSheet |
| Same(4) | 禁止 | NodeSend_53_SameSheet_To_HeLiu | 禁止 | NodeSend_53_SameSheet_To_HeLiu | NodeSend_11 | 禁止 |
| UnSame(5) | 禁止 | NodeSend_53_UnSameSheet_To_HeLiu | 禁止 | NodeSend_53_UnSameSheet_To_HeLiu | 禁止 | NodeSend_11 |
附录 C ActionType 轨迹类型一览
| 值 | 枚举名 | 中文 | 所属操作 |
|---|---|---|---|
| 0 | Start | 发起 | 启动 |
| 1 | Forward | 前进 | 发送 |
| 2 | Return | 退回 | 退回 |
| 3 | Shift | 移交 | 移交 |
| 4 | UnShift | 撤销移交 | 移交 |
| 5 | UnSend | 撤销发送 | 撤销 |
| 6 | ForwardFL | 分流前进 | 发送 |
| 7 | ForwardHL | 合流前进 | 发送 |
| 8 | FlowOver | 流程结束 | 发送 |
| 9 | CallChildenFlow | 调用子流程 | 父子流程 |
| 10 | StartChildenFlow | 启动子流程 | 父子流程 |
| 11 | SubThreadForward | 子线程前进 | 发送 |
| 15 | Hungup | 挂起 | 挂起 |
| 16 | UnHungup | 解除挂起 | 挂起 |
| 18 | Press | 催办 | 催办 |
| 19 | DeleteFlowByFlag | 逻辑删除 | 删除 |
| 20 | UnDeleteFlowByFlag | 恢复删除 | 删除 |
| 24 | AskforHelp | 加签 | 加签 |
| 25 | ForwardAskfor | 加签转发 | 加签 |
| 30 | HuiQian | 会签 | 会签 |
| 31 | Adjust | 调整 | 实例操作 |
| 201 | ReturnAndBackWay | 退回并原路返回 | 退回 |
附录 D 关键数据表字段说明
WF_GenerWorkFlow
| 字段 | 含义 |
|---|---|
| WorkID | 主键,工作实例 ID |
| FID | 干流程 WorkID(分合流) |
| FK_Flow | 流程编号 |
| FK_Node | 当前节点 ID |
| WFState | 流程状态 |
| TodoEmps | 当前待办人员 |
| PWorkID | 父流程 WorkID(父子流程) |
| PFlowNo | 父流程编号 |
| AtPara | 扩展参数(ThreadCount 等) |
WF_GenerWorkerList
| 字段 | 含义 |
|---|---|
| WorkID | 工作实例 ID |
| FID | 干流程 WorkID |
| FK_Node | 节点 ID |
| FK_Emp | 处理人工号 |
| IsPass | 0=待办, 1=已办, -1=未到, 80=不可见 |
附录 E 前端设计器节点形状与 RunModel 映射表
| RunModel | 形状 ID | 标签 | 多边形类型 |
|---|---|---|---|
| 0 | userNodes[0] | 线性 | 矩形 |
| 1 | userNodes[12] | 合流 | 倒梯形 |
| 2 | userNodes[13] | 分流 | 正梯形 |
| 3 | userNodes[14] | 分合流 | 六角形 |
| 4 | userNodes[15] | 同表单 | 平行四边形 |
| 5 | userNodes[16] | 异表单 | 梯形 |
| SubFlowNode(3) | subFlowNodes[0] | 子流程 | 六边形 |
附录 F 核心源码文件索引
| 分类 | 文件路径 | 核心类/方法 |
|---|---|---|
| 发送引擎 | CCFlow/Components/BP.WF/WF/WorkNode.cs | NodeSend(), NodeSend_Send_5_5() |
| 退回引擎 | CCFlow/Components/BP.WF/WF/WorkReturn.cs | DoIt(), ExeReturn*() |
| 撤销引擎 | CCFlow/Components/BP.WF/WF/WorkUnSend.cs | DoUnSend() |
| 移交 | CCFlow/Components/BP.WF/WF/ShiftWork.cs | Node_Shift_ToEmp() |
| 流程操作 | CCFlow/Components/BP.WF/WF/WorkFlow.cs | DoHungup(), DoDelete* |
| 调整 | CCFlow/Components/BP.WF/WF/WorkReSend.cs | DoIt() |
| 子流程 | CCFlow/Components/BP.WF/Template/SFlow/ | FrmSubFlow, SubFlowAuto |
| 枚举 | CCFlow/Components/BP.WF/EnumLib.cs | RunModel, TodolistModel, ReturnRole |
| API 门面 | CCFlow/Components/BP.WF/Dev2Interface.cs | 全部对外 API |
| HTTP 入口 | CCFlow/Components/BP.WF/HttpHandler/WF_WorkOpt.cs | 全部操作 HTTP 接口 |
| 设计器 | Vue3/src/WF/Admin/FlowDesignerV2/ | index.vue, shapes/index.ts |
| 运行态 | Vue3/src/WF/ | MyFlow.vue, MyFLDealThread.vue |
附录 G 接收人规则 DeliveryWay 摘要
FindWorker.cs 根据节点 DeliveryWay 计算下一节点接收人,常用规则如下:
| 值 | 枚举名 | 含义 | 典型场景 |
|---|---|---|---|
| 0 | ByStation | 按角色 | 部门经理审批 |
| 1 | ByDept | 按部门 | 本部门全员 |
| 2 | BySQL | 按 SQL | 动态计算 |
| 4 | BySelected | 发送人选择 | 自由选人 |
| 5 | ByPreviousNodeFormEmpsField | 表单字段 | 主表人员字段 |
| 6 | ByPreviousNodeEmp | 与上一步相同 | 退回重审 |
| 7 | ByStarter | 与发起人相同 | 退回修改 |
| — | ByDtlAsSubThreadEmps | 明细表行 | 同表单分流按行分派 |
完整枚举见 EnumLib.cs 第 959 行起,共 30+ 种规则。
附录 H 阻塞模式 BlockModel 摘要
| 值 | 枚举名 | 含义 |
|---|---|---|
| 0 | None | 不阻塞 |
| 1 | CurrNodeAll | 当前节点子线程未全部完成则阻塞 |
| 2 | SpecSubFlow | 按约定格式阻塞 |
| 3 | BySQL | SQL 返回值 ≥1 则阻塞 |
| 4 | ByExp | 表达式阻塞 |
| 5 | SpecSubFlowNode | 指定子流程未到某节点则阻塞 |
| 6 | SameLevelSubFlow | 平级子流程未到某节点则阻塞 |
全文完
插图清单提醒(共 18 处,需作者自行绘制或截图):
图号 位置 内容 建议素材 图1 第 3.1 节 CCFlow 工作流子系统分层架构图 Visio / draw.io 四层框图 图2 第 3.2 节 汽车类比模型示意图 汽车侧视图 + 标注箭头 图3 第 3.3.3 节 WorkID / FID / PWorkID 关系 ER 图 ER 工具绘制 图4 第 4.4 节 线形流程拓扑与方向条件示意图 FlowDesignerV2 截图 图5 第 5.4.2 节 同表单分合流时序图 UML 时序图 图6 第 6.3 节 同表单 vs 异表单分合流对比图 左右对比表 + 数据表示意 图7 第 7.4 节 父子流程生命周期状态图 双状态机图 图8 第 8.4 节 四大模式组合示例图 完整流程设计器截图 图9 第 9.1 节 节点通用操作与汽车类比对照图 图标 + 操作名 图10 第 9.7 节 前加签与后加签流程对比图 泳道图 图11 第 10.1 节 流程调整前后状态对比图 调整前后节点高亮 图12 第 11.2 节 5×5 发送矩阵示意图 矩阵表 + switch 伪代码 图13 第 12.1 节 多人处理规则示意图 五种模式泳道图 图14 第 13.2 节 退回规则与可退节点计算流程图 流程图 图15 第 14.1 节 采购申请案例流程图 设计器 + 待办截图 图16 第 14.2 节 项目立项异表单分合流案例图 ER 图 + 三表单截图 图17 第 14.3 节 合同审批父子流程案例图 双泳道 + PWorkID 标注 图18 第 14.4 节 请假审批线形流程案例图 线性图 + TodolistModel 标注 表清单提醒(文中已含 40+ 张表,投稿时可按期刊要求将核心表(表1 四大模式对比、表2 汽车类比、表3 5×5 矩阵、表4 通用操作总览)编号为正式表1–表4。)

406

被折叠的 条评论
为什么被折叠?



