spec.md 42 KB

业务模块与流程模块通用联动架构落地方案

status: proposed created: 2026-06-28 complexity: 🔴 复杂 related: code-copilot/changes/lowcode-app-full-loop-optimization/spec.md, code-copilot/changes/form-first-business-object-designer/spec.md, code-copilot/changes/lowcode-runtime-datasource-isolation/spec.md

1. 背景

参考文档 /Users/yaomindong/Desktop/project/mdframe/shenrong/shenrong-projman/code-copilot/knowledge/business-flow-fast-adaptation-guide.md 的核心判断是:

flow 管通用流转,business 管业务规则

这个方向与 Forge 当前架构决策一致:审批不再建设独立审批引擎,统一归入 Flowable 流程引擎;低代码业务对象已经围绕“表单优先、动态 CRUD、单据配置、流程绑定、触发器、消息、报表”形成主链路。

但 Forge 不是传统手写业务系统。当前工程已经具备:

  • 低代码对象设计器、表单设计器、字段注册、运行态动态 CRUD。
  • 单据模式配置、状态映射、运行态操作按钮、流程进度展示。
  • BusinessFlowService 动态发起流程、写入 ai_business_flow_instance_link、回写单据状态。
  • Flow 客户端、Flow 事件 Redis/Webhook 发布、租户上下文分发。
  • Flow 入口表单创建低代码业务记录的桥接能力。

因此参考方案里“新增 BusinessFlowAdapter + AbstractBusinessFlowService”不能原样作为主方案。它适合手写业务模块,但对 Forge 低代码平台来说,应升级为:

业务对象流程契约 + 运行时流程网关 + 流程事件桥 + 低代码发布编译

目标不是让每个新流程少写几个 Service 方法,而是让低代码用户完成:

表单创建 -> 单据生命周期 -> 流程配置 -> 节点表单/权限 -> 发布检查 -> 运行态填报/审批/回写/消息

2. 现状评估

2.1 已经合理的现有能力

  1. BusinessFlowService 已承担低代码业务对象与流程引擎的动态集成。

    • ai_business_binding 读取 binding_type=FLOW 配置。
    • 从动态 CRUD 读取业务记录。
    • 根据变量映射构建流程变量。
    • 调用 FlowClient.startProcess 发起流程。
    • 写入 ai_business_flow_instance_link
    • 按流程结果回写单据状态并发布业务事件。
  2. BusinessDocumentRuntimeService 已把单据状态、流程实例、可执行动作合并为运行态协议。

    • AiCrudPage 可根据运行态动作显示“发起主流程”。
    • 详情页可展示流程时间轴和流程图。
  3. Flow 侧已经具备事件发布和租户上下文能力。

    • FlowTaskEventListener 发布 TASK_CREATEDTASK_COMPLETEDPROCESS_COMPLETEDPROCESS_REJECTEDPROCESS_CANCELED
    • FlowEventMessage 已携带 tenantIdbusinessKeyprocessInstanceIdprocessDefKeytaskDefKeyvariables 等关键字段。
    • FlowEventSubscriber 收到事件后会用 TenantContextHolder 分发。
  4. 低代码设计器已经具备流程配置入口。

    • BusinessDocumentPanel 配置单据模式、编号、状态映射、流程展示开关。
    • BusinessFlowBindingPanel 配置流程模型、发起方式、标题模板和变量映射。
    • FlowVariableMappingEditor 支持推荐映射。
  5. Flow 入口表单也能反向创建低代码业务记录。

    • FlowBusinessObjectRuntimeAdapterImpl 支持 BUSINESS_OBJECT/HYBRID 数据模式。
    • 这为长期“从流程入口表单创建业务单据”提供了基础。

2.2 仍然存在的核心问题

  1. 集成层协议偏薄。

    • 当前只覆盖默认流程、标题模板、变量映射和简单状态回写。
    • 缺少完整的“业务对象流程契约”,无法统一描述流程版本、节点表单、字段权限、驳回重提、撤回、抄送、回调策略、幂等策略和副作用。
  2. 两条链路尚未统一。

    • 链路 A:业务单据运行页发起流程。
    • 链路 B:流程入口表单创建业务记录后启动流程。
    • 两者都写 ai_business_flow_instance_link,但记录主键、变量快照、状态机、表单快照和回调语义没有统一契约。
  3. 事件消费不适合动态低代码主流程。

    • FlowEventSubscriber 面向 @FlowBind(modelKey=...) 的手写 Bean 分发。
    • 低代码流程模型是运行时配置,不能要求每个模型生成一个手写 @FlowBind Bean。
    • 需要一个平台级 BusinessFlowEventBridge 订阅所有 Flow 事件,再按 businessKey/objectCode/processDefKey 路由到低代码对象。
  4. 记录主键协议不够通用。

    • BusinessFlowStartDTO.recordIdAiBusinessFlowInstanceLink.recordIdTaskFormInfo.recordIdFlowBusinessObjectRuntimeAdapter.BusinessRecordCreateResult.recordId 当前是 Long
    • 低代码运行时已支持自定义单字段主键和多数据源,流程链路仍未完全适配。
  5. 驳回修改重提没有产品级协议。

    • 参考文档指出“驳回到发起人修改节点”不是流程终态,这个判断正确。
    • 当前 BusinessFlowService.normalizeCallbackResult 只按最终结果回写 APPROVED/REJECTED/CANCELED,缺少 TASK_COMPLETED + approvalResult=reject + modifyTaskKey 的中间状态处理。
  6. 审批办理页与业务详情页仍会分叉。

    • Flow 侧 TaskFormInfo 支持动态表单、外部表单、表单快照和字段权限。
    • 低代码业务详情页使用 AiCrudPage/AiForm/FieldValueRenderer
    • 待办审批时缺少统一的 BUSINESS_OBJECT_FORM 表单类型来复用业务对象详情/编辑渲染和字段权限。
  7. 发布检查与流程配置还不够一体化。

    • 单据配置和流程绑定目前是两个面板。
    • 发布时应把状态字段、流程模型、变量映射、节点表单权限、按钮权限和触发器动作作为一个整体检查。
  8. 可观测性和验收模板不足。

    • 已有 Flow 错误日志、触发器日志、站内消息。
    • 但缺少业务流程链路级 trace:一次发起、变量、Flow 实例、事件回调、状态回写、触发器副作用、消息推送应该能按 correlationId 串起来。

3. 对参考建议的合理性判断

参考建议 判断 Forge 落地方式
flow 管通用流转,business 管业务规则 直接采纳 Flow 只负责模型、实例、任务、事件;业务对象负责状态字段、变量、数据权限、副作用。
BusinessFlowAdapter 改造采纳 手写业务模块可用 Adapter;低代码主链路应以 BusinessFlowContract + BusinessFlowGateway 替代每业务 Service 继承。
建业务流程元数据配置 直接采纳但复用现有表 复用 ai_business_bindingai_business_document_configai_business_flow_instance_link,补充发布态契约快照,不另起重复配置表。
流程模型关联业务表并配置状态字段 分层采纳 这是最小可用集成层,适合低代码对象和简单业务表;Forge 需要扩展为 businessBinding,同时保留复杂代码业务 Adapter。
统一事件协议携带 tenantId/businessKey/processInstanceId/taskDefKey/variables 直接采纳 现有事件字段基本具备;补 eventIdcorrelationIdobjectCoderecordKeytaskResultformInstanceId
BPMN 模板库 直接采纳 接入 Flow 设计器和 AI 生成器,模板产出 BPMN、变量清单、节点表单权限默认值和发布检查规则。
驳回修改重提固化为框架能力 直接采纳 作为 rejectStrategy=RETURN_TO_MODIFY_TASK 的契约能力,不要求每个业务对象手写逻辑。
流程脚手架 改造采纳 对代码生成模块生成手写业务骨架;对低代码对象生成运行态契约和流程模板,不生成大量重复 Java。
每条流程手动写 Flyway、菜单、权限 不作为低代码主路径 手写模块仍需要;低代码应用应通过对象发布自动生成菜单、按钮权限和运行态配置。

4. 目标架构

4.1 总体链路

设计态
Form Designer
    -> Business Object Designer
    -> Document Lifecycle
    -> Flow Binding / Flow Template
    -> Node Form Permission
    -> Publish Validator
    -> BusinessFlowContract Snapshot

运行态发起
AiCrudPage / FlowEntry / Trigger
    -> BusinessFlowGateway
    -> BusinessRecordRuntimeFacade
    -> FlowClient
    -> Flowable
    -> ai_business_flow_instance_link

运行态事件
FlowTaskEventListener
    -> FlowEventPublisher / Webhook
    -> BusinessFlowEventBridge
    -> BusinessFlowStateMachine
    -> DynamicCrud internal update
    -> BusinessEventPublisher
    -> Trigger / Message / Report Metrics

审批办理
Flow Todo
    -> TaskFormInfo
    -> BusinessTaskFormContext
    -> Lowcode Business Form Renderer
    -> Approve / Reject / Return / Resubmit

4.2 模块职责

Flow 模块

  • 管理 Flowable 模型、版本、部署、流程实例和任务。
  • 处理通过、驳回、撤回、终止、转办、签收、会签等流程动作。
  • 发布流程事件。
  • 提供流程图、历史、任务表单、节点权限、抄送、站内待办消息。
  • 提供通用组织/角色/SPEL 解析能力。
  • 不直接查询低代码业务表,不直接决定业务状态。

Business / Lowcode 模块

  • 管理业务对象、字段、表单、列表、详情、单据、权限和发布态配置。
  • 管理业务状态字段和状态流转规则。
  • 构建流程变量。
  • 解析业务相关审批人变量,例如项目负责人、合同负责人、记录负责人。
  • 维护业务记录与流程实例关联。
  • 消费流程事件并回写业务状态。
  • 执行流程完成后的业务副作用,例如创建关联记录、更新字段、发送消息、刷新统计。

Code-first 复杂业务模块

不是所有业务都适合低代码建模。资金、库存、合同、订单、外部系统集成、复杂状态机等代码优先业务,应保留自己的领域模型、数据库表、事务边界和 Service 编排。

这类业务接入流程时遵循:

  • 业务模块自己负责业务校验、状态机、领域副作用和数据一致性。
  • Flow 仍只负责流程模型、任务流转、审批动作、流程事件和流程历史。
  • 平台提供统一接入 SDK/Adapter,让代码业务复用 BusinessFlowGatewayBusinessFlowEventBridge、流程 trace、待办表单上下文和标准验收模板。
  • 业务模块不需要写低代码对象配置,也不要求迁移到动态 CRUD。
  • 业务模块必须显式注册 businessType/objectCode/modelKey/businessKey 规则,避免流程事件无法路由。

通用联动层

新增或重构为以下平台服务:

服务 作用
BusinessFlowContractService 读取/保存/发布业务对象流程契约,兼容现有 ai_business_binding 和单据配置。
BusinessFlowGateway 统一发起、撤回、取消、重提、查询运行态、更新变量,不让页面和触发器直接拼 FlowClient 调用。
BusinessRecordRuntimeFacade 屏蔽动态 CRUD、运行数据源、主键类型、租户、审计字段和内部状态更新。
BusinessFlowEventBridge 订阅 Flow 全量事件,按业务键和流程契约路由到低代码对象。
BusinessFlowStateMachine 将流程事件、节点结果、单据状态映射成可审计的业务状态变更。
BusinessTaskFormContextService 为待办页输出低代码业务表单上下文、字段权限和审批动作策略。
BusinessFlowTraceService 记录发起、回调、状态回写、触发器和消息的链路日志。
BusinessFlowAdapterRegistry 注册代码优先业务模块的流程适配器,按 businessType/modelKey/businessKey 路由事件。
BusinessFormAssetRegistry 汇聚低代码表单、Flow 动态表单、代码表单和外部表单资产,供设计器选择和待办页解析。

5. 核心契约设计

5.1 BusinessFlowContract

发布态应形成一份业务对象流程契约。首期可以存入 ai_business_binding.binding_config 和设计版本快照,后续如版本化需求增强,再独立成 ai_business_flow_contract_version

{
  "schemaVersion": "1.0",
  "objectCode": "crm_opportunity",
  "configKey": "crm_opportunity_runtime",
  "recordKey": {
    "primaryField": "id",
    "valueType": "STRING",
    "businessKeyPattern": "${objectCode}:${recordKey}"
  },
  "businessBinding": {
    "mode": "LOWCODE_OBJECT",
    "tableName": "crm_opportunity",
    "primaryKeyField": "id",
    "tenantField": "tenant_id",
    "statusField": "document_status",
    "titleField": "opportunity_name"
  },
  "document": {
    "enabled": true,
    "statusField": "documentStatus",
    "statusMapping": {
      "DRAFT": "DRAFT",
      "IN_PROCESS": "IN_PROCESS",
      "APPROVED": "APPROVED",
      "REJECTED": "REJECTED",
      "CANCELED": "CANCELED"
    }
  },
  "mainFlow": {
    "flowModelKey": "crm_opportunity_approval",
    "flowModelVersionPolicy": "LATEST_ON_START",
    "startMode": "MANUAL_AND_TRIGGER",
    "titleTemplate": "${opportunityName}-商机审批",
    "rejectStrategy": "RETURN_TO_MODIFY_TASK",
    "modifyTaskKey": "initiator_modify_task"
  },
  "variableMapping": [
    {
      "formField": "amount",
      "flowVariable": "amount",
      "required": true
    },
    {
      "formField": "ownerId",
      "flowVariable": "businessOwnerId",
      "resolver": "FIELD_VALUE"
    }
  ],
  "nodeForms": [
    {
      "taskDefKey": "dept_manager_task",
      "formMode": "BUSINESS_OBJECT_FORM",
      "viewKey": "approval_detail",
      "fieldPermissions": {
        "amount": "READONLY",
        "approvalComment": "EDITABLE"
      }
    },
    {
      "taskDefKey": "initiator_modify_task",
      "formMode": "BUSINESS_OBJECT_FORM",
      "viewKey": "reject_modify",
      "editableFields": ["amount", "expectedCloseDate", "remark"]
    }
  ],
  "events": {
    "onStarted": {
      "status": "IN_PROCESS"
    },
    "onApproved": {
      "status": "APPROVED",
      "publishBusinessEvent": "FLOW_APPROVED"
    },
    "onRejected": {
      "status": "REJECTED",
      "publishBusinessEvent": "FLOW_REJECTED"
    },
    "onCanceled": {
      "status": "CANCELED",
      "publishBusinessEvent": "FLOW_CANCELED"
    }
  },
  "options": {
    "allowDuplicateRunning": false,
    "eventIdempotent": true,
    "detailFlowTimelineVisible": true,
    "detailFlowDiagramVisible": true
  }
}

5.2 业务表绑定规则

类似 JeecgBoot 在流程模型里关联业务表、配置流程状态字段的做法,在 Forge 中可以作为首期最小闭环能力,但要放进业务流程契约,而不是散落在 BPMN 模型属性里。

建议抽象为 businessBinding

字段 说明
mode LOWCODE_OBJECTBUSINESS_TABLEADAPTER
tableName 业务表名,低代码对象可由发布态配置自动生成
primaryKeyField 业务记录主键字段
tenantField 租户字段,默认 tenant_id
statusField 流程/单据状态字段
titleField 流程标题默认取值字段,可选
ownerField 业务负责人字段,可选,用于变量推荐

三种使用方式:

模式 适用对象 回写方式
LOWCODE_OBJECT 低代码创建的业务对象 由对象元数据自动生成表名、主键、状态字段,BusinessRecordRuntimeFacade 回写。
BUSINESS_TABLE 简单代码业务,只有状态同步和基础详情 开发者配置白名单表和字段,平台只做状态字段、流程实例关联和标题读取。
ADAPTER 合同、采购、库存、资金等复杂业务 不直接改业务表,由 BusinessFlowAdapter 调业务 Service 完成校验、状态机和副作用。

边界很重要:业务表绑定只能解决“流程实例关联哪条业务记录、状态字段怎么同步”。它不能替代变量构建、节点表单资产、字段权限、驳回修改重提、业务副作用和复杂事务。

安全约束:

  • tableName/fieldName 必须来自发布态元数据或开发者注册白名单,禁止前端传什么就拼什么。
  • 更新状态必须走 BusinessRecordRuntimeFacade,统一租户、数据源、审计字段和幂等控制。
  • 代码优先复杂业务默认不允许平台直接 UPDATE table SET statusField = ?,除非业务模块明确选择 BUSINESS_TABLE 简化模式。

5.3 businessKey 规则

统一使用:

${objectCode}:${recordKey}

要求:

  • objectCode 必须是发布态业务对象编码,不能使用页面临时 configKey
  • recordKey 首期兼容 Long,后续必须升级为 String,支持自定义单字段主键。
  • 解析工具集中到 BusinessKeyCodec,禁止散落 split(":", 2)
  • businessKey 不承载租户,租户来自 tenantId 字段和租户上下文。

5.4 流程变量规则

系统变量统一注入:

变量 来源
tenantId 当前租户
objectCode 业务对象
configKey 发布态动态 CRUD 配置
recordKey 业务记录主键,字符串
recordId 兼容字段,仅 Long 主键时保留
businessKey ${objectCode}:${recordKey}
startUserId 发起人
startDeptId 发起部门

业务变量来自 variableMapping。业务相关审批人必须在 Business 侧提前解析为变量,BPMN 只消费变量,不直接查业务表。

5.5 状态机规则

标准单据状态:

标准状态 说明
DRAFT 草稿,可编辑、可删除、可发起流程
IN_PROCESS 流程中,主数据默认只读
REJECTED 已驳回,可按策略修改后重提
APPROVED 已通过,不可编辑
CANCELED 已撤回/取消
CLOSED 业务关闭

事件映射:

Flow 事件 条件 业务动作
PROCESS_STARTED 发起成功 写关联记录,状态置 IN_PROCESS
TASK_CREATED 任意节点 可记录节点待办,不直接改主状态
TASK_COMPLETED approvalResult=reject 且目标为修改节点 状态置 REJECTED,流程仍为 RUNNING
TASK_COMPLETED 修改节点重提 保存业务数据,更新流程变量,状态置 IN_PROCESS
PROCESS_COMPLETED 非 reject 终态 状态置 APPROVED,发布 FLOW_APPROVED
PROCESS_COMPLETED reject 终态 状态置 REJECTED,发布 FLOW_REJECTED
PROCESS_CANCELED 撤回/取消 状态置 CANCELED,发布 FLOW_CANCELED

5.6 待办表单上下文

TaskFormInfo.formType 基础上新增低代码业务表单类型:

BUSINESS_OBJECT_FORM

返回字段:

{
  "formType": "BUSINESS_OBJECT_FORM",
  "formRef": {
    "type": "BUSINESS_OBJECT_FORM",
    "code": "crm_opportunity_default",
    "viewKey": "approval_detail"
  },
  "objectCode": "crm_opportunity",
  "configKey": "crm_opportunity_runtime",
  "recordKey": "10001",
  "businessKey": "crm_opportunity:10001",
  "viewKey": "approval_detail",
  "mode": "APPROVE",
  "fieldPermissions": {},
  "runtimeRules": {},
  "editMode": "READONLY_APPROVE",
  "processInstanceId": "...",
  "taskId": "..."
}

前端待办页据此复用低代码表单渲染器或代码表单 Provider,而不是要求每条流程配置外部 Vue 页面。

首期落地采用“Flow 基础任务表单 + 业务侧表单上下文”双段解析:

  • forge-plugin-flow 继续只输出通用 TaskFormInfo,不反向依赖低代码/业务插件。
  • 待办页读取 TaskFormInfo 后,再调用 GET /ai/business/flow/task-form-context,由业务侧按 businessKey/processInstanceId/taskDefKey 解析 nodeForms、业务记录、低代码表单字段和字段权限。
  • 低代码业务表单保存走 PUT /ai/business/flow/task-form-context,后端只写当前节点配置为 writable=true 的字段。
  • BUSINESS_CODE_FORM 保持 Provider 协议预留,复杂代码业务后续通过注册目录或跳转业务详情页接入,仍不让普通用户手工输入组件路径。

6. 数据模型落地

6.1 首期复用与扩展现有表

不新增重复的“流程业务绑定表”,优先复用:

当前用途 目标用途
ai_business_binding 对象能力绑定,含 FLOW 保存主流程契约概要和兼容字段
ai_business_document_config 单据配置、状态映射 保存单据生命周期配置
ai_business_flow_instance_link 单据与流程实例关联 扩展为流程实例运行态主索引
ai_business_trigger 触发器 消费 FLOW_* 业务事件执行副作用
ai_business_trigger_log 触发器日志 增加流程链路关联和 TODO/失败原因
ai_crud_config 动态 CRUD 发布态 挂接运行数据源、对象编码、页面配置
ai_business_object_design_version 设计版本快照 保存完整流程契约设计态快照
ai_business_form_asset 可新增轻量索引表 保存低代码/Flow/外部表单资产元数据;代码表单可由 Provider 运行时注册并同步展示

6.2 建议扩展字段

ai_business_flow_instance_link 建议扩展:

字段 说明
record_key varchar(128) 通用主键字符串,替代长期依赖 record_id bigint
config_key varchar(128) 发布态动态 CRUD 配置
flow_definition_id varchar(128) 实际启动的流程定义 ID
flow_definition_version int 实际启动版本
contract_version_id bigint 关联发布态契约版本
correlation_id varchar(64) 发起、回调、触发器、消息共用链路 ID
current_task_key varchar(128) 当前关键任务节点
last_event_type varchar(64) 最近一次事件
last_event_time datetime 最近事件时间

ai_business_binding.binding_config 建议扩展:

  • schemaVersion
  • recordKey
  • mainFlow
  • variableMapping
  • nodeForms
  • events
  • options

后续如需要流程契约版本独立发布,再新增:

ai_business_flow_contract_version

用于锁定“业务对象版本 -> 流程模型版本 -> 表单权限版本 -> 状态映射版本”,避免运行中流程被设计态变更影响。

7. 后端接口设计

7.1 配置接口

沿用并增强现有 /ai/business/flow

接口 用途
GET /ai/business/flow/binding/{objectCode} 查询流程契约概要
PUT /ai/business/flow/binding/{objectCode} 保存流程契约草稿
GET /ai/business/flow/model/{modelKey}/variables 解析流程变量候选项
POST /ai/business/flow/contract/{objectCode}/validate 发布前校验流程契约
POST /ai/business/flow/contract/{objectCode}/publish 编译并发布流程契约快照
GET /ai/business/form-assets 查询可选表单资产,支持按 objectCode/businessType/source 过滤
GET /ai/business/form-assets/{formCode}/views 查询表单可选视图,如审批详情、负责人补充、驳回修改
GET /ai/business/form-assets/{formCode}/field-catalog 查询表单字段或虚拟区域目录,供节点权限配置

7.2 运行接口

接口 用途
POST /ai/business/flow/start 手动或触发器发起主流程
POST /ai/business/flow/{businessKey}/withdraw 发起人撤回
POST /ai/business/flow/{businessKey}/cancel 业务取消
POST /ai/business/flow/resubmit 驳回修改后重提,复杂业务页保存后调用
GET /ai/business/flow/status/{objectCode}/{recordKey} 查询流程运行态
GET /ai/business/flow/task-form-context 给待办页返回业务表单上下文
PUT /ai/business/flow/task-form-context 保存当前任务节点授权的业务字段

7.3 内部回调接口

两种方式必须统一到同一个 service:

入口 场景
Redis flow:event:all Admin 与 Flow 共 Redis 或分服务部署
POST /ai/business/flow/callback Flow Webhook 或兼容手动回调

内部统一调用:

BusinessFlowEventBridge.handle(FlowEventContext context)

不允许页面、触发器、手写业务 Service 分别实现状态回写。

7.4 代码优先业务接入面

复杂业务不走低代码对象契约时,提供三种接入方式,按复杂度递进:

模式 适用场景 特点
Gateway API 模式 业务 Service 已有完整状态机,只需要发起流程和查询进度 业务代码主动调用 BusinessFlowGateway.startCodeFirstFlow(...),自己处理状态更新。
Adapter 模式 需要复用平台事件桥、trace、待办表单和标准状态回调 实现 BusinessFlowAdapter,平台统一调用 validateBeforeStart/buildVariables/onApproved/onRejected/onCanceled
Annotation 兼容模式 已有 @FlowBind/@FlowCallback 老代码 保留可用,但新复杂业务优先转 Adapter,避免事件处理散落。

建议接口:

public interface BusinessFlowAdapter {

    String businessType();

    String objectCode();

    String modelKey();

    String buildBusinessKey(Object businessId);

    FlowBusinessSnapshot loadBusiness(String businessKey);

    Map<String, Object> buildStartVariables(FlowStartRequest request);

    void validateBeforeStart(FlowStartRequest request);

    void markInProcess(FlowStartRequest request, FlowStartResult result);

    void onTaskCompleted(FlowEventContext context);

    void onApproved(FlowEventContext context);

    void onRejected(FlowEventContext context);

    void onCanceled(FlowEventContext context);

    default BusinessTaskFormContext buildTaskFormContext(FlowEventContext context) {
        return BusinessTaskFormContext.externalDetail();
    }
}

代码优先业务推荐调用链:

业务 Controller
    -> 业务 Service 校验和保存草稿
    -> BusinessFlowGateway.start(adapterCode, businessId, variables)
    -> FlowClient.startProcess
    -> BusinessFlowEventBridge
    -> BusinessFlowAdapterRegistry
    -> 业务 Adapter 回写状态/执行副作用

设计约束:

  • Adapter 的 onApproved/onRejected/onCanceled 必须幂等。
  • Adapter 内查询类 SQL 仍按项目规范写 Mapper XML,不在 Service 拼复杂查询。
  • 资金、库存、权限放开等高风险副作用必须在业务 Service 内显式审计,不能只靠流程回调默认处理。
  • 待办页业务详情可以返回外部业务详情路由,也可以返回 BUSINESS_CODE_FORM 上下文,由业务模块提供只读/编辑组件。
  • 平台只保存流程实例关联、trace 和流程上下文,不强制保存业务主数据。

7.5 表单资产选择与节点字段权限

当前流程配置里让用户手工输入 formUrl 或组件路径不合理。业务用户不知道表单地址,开发者也容易输入错路径,后续迁移路由时还会造成历史 BPMN 失效。

目标设计是:流程节点不直接保存 URL,而是保存“表单资产引用 + 节点表单策略”。

7.5.1 表单资产注册

建立统一表单资产目录,来源可以是低代码、Flow 动态表单或代码表单。

表单来源 示例 面向用户的选择方式 运行时解析
低代码业务表单 商机详情表单、采购合同编辑表单 下拉选择业务对象 + 表单视图 BUSINESS_OBJECT_FORM
Flow 动态表单 简单请假表单、节点补充信息表单 下拉选择流程表单 dynamic/formKey
代码表单 采购合同审批详情、合同变更页 下拉选择代码注册的表单资产 BUSINESS_CODE_FORM
外部地址 历史系统页面、第三方页面 高级模式输入 URL external/formUrl

代码表单由业务模块显式注册,不让用户输入路径。首期服务端扩展点已落地为 BusinessCodeFormProvider

public interface BusinessCodeFormProvider {

    String providerKey();

    default String providerName();

    default List<Map<String, Object>> formAssets(String objectCode);

    BusinessTaskFormContextVO buildContext(BusinessTaskFormContextQueryDTO query,
                                           Map<String, Object> formRef,
                                           List<Map<String, Object>> fieldPermissions);

    default BusinessTaskFormContextVO saveContext(BusinessTaskFormSaveDTO dto,
                                                  Map<String, Object> formRef,
                                                  List<Map<String, Object>> fieldPermissions);
}

业务模块注册 Provider 后,GET /ai/business/flow/form-assets/{objectCode} 会合并代码表单资产;待办页解析到 BUSINESS_CODE_FORM 时由 Provider 返回业务页地址、字段/区域目录或自定义上下文。

注册方式可以有两种:

  • 注解注册:@BusinessForm(formCode="purchase_contract_approval", formName="采购合同审批表单")
  • 配置注册:business-flow.forms[],适合不方便加注解的历史模块。

流程设计器节点表单配置应展示为选择器:

表单类型:继承业务主表单 / 低代码表单 / 流程动态表单 / 代码表单 / 外部地址
表单资产:采购合同审批表单
表单视图:审批详情 / 负责人补充 / 驳回修改

只有“外部地址”作为高级模式保留手工输入。

7.5.2 节点表单策略

每个人工节点保存 NodeFormPolicy

{
  "taskDefKey": "contract_owner_fill_task",
  "formRef": {
    "type": "BUSINESS_CODE_FORM",
    "code": "purchase_contract_approval",
    "viewKey": "owner_fill"
  },
  "mode": "FILL",
  "fieldPolicies": [
    {
      "field": "contractName",
      "visible": true,
      "editable": false,
      "required": false
    },
    {
      "field": "purchaseListAttachment",
      "visible": true,
      "editable": true,
      "required": true
    }
  ],
  "actionPolicies": {
    "approve": false,
    "submit": true,
    "reject": false
  }
}

字段策略分层:

  1. 表单设计默认权限:字段是否默认显示、默认必填。
  2. 节点字段权限:当前节点覆盖默认权限,支持可见、只读、可编辑、必填。
  3. 运行时规则:按业务状态、用户、金额、部门等动态隐藏或只读。
  4. 后端提交校验:最终以服务端策略为准,前端只负责渲染。

对于代码表单,字段目录由 BusinessCodeFormProvider.formAssets() 提供。复杂页面如果无法拆成字段,可以把“区域、附件区、操作按钮”抽象成虚拟字段:

baseInfoSection
contractAmount
purchaseListAttachment
riskReviewSection
submitButton

这样流程节点仍能统一控制“哪个节点显示哪个区域、哪个字段可编辑”。

7.5.3 采购合同审批示例

采购合同审批建议拆成几个节点:

节点 节点类型 表单策略
发起节点 填报 合同基础信息、金额、供应商、附件可编辑
负责人补充清单 办理/填写任务 只让负责人编辑 purchaseListAttachment,其他字段只读
部门负责人审批 审批 基础信息和清单可见,全部只读,只填审批意见
法务审批 审批 合同条款、附件可见,只读,可上传法务意见附件
财务审批 审批 金额、付款条款可见,只读,可填财务意见

“只有负责人节点显示上传清单”不建议靠不同 Vue 路径解决,而应靠同一个表单资产 + 不同 viewKey/fieldPolicies 控制。这样后续新增节点时不用新增页面。

7.5.4 驳回修改的产品策略

主流 BPM / 低代码产品的共同思路是“任务绑定表单资产”,而不是让普通用户维护页面路径。Camunda 的 Web Modeler 支持把用户任务链接到同项目表单,并明确推荐 linked form,避免每次变更都复制 JSON;自定义 form key 更偏向外部应用集成。Flowable Form 也以表单 key、字段、outcomes 描述表单定义,任务页展示当前任务对应表单,SaveComplete 分离,outcome 变量再驱动后续流转。参考:

因此 Forge 的产品默认策略应是:

  • 设计态选择表单资产,保存 formRef,不保存裸 formUrl 作为主配置。
  • 待办页按当前任务解析表单资产、字段权限、动作按钮和流程上下文。
  • 代码表单通过 Provider 暴露可控字段/区域目录,外部 URL 只作为高级兼容能力。
  • 审批动作和业务修改动作分离,保存草稿完成任务保存并重提 是不同语义。

主流做法不是让任意审批人在任意审批表单里随意修改业务主数据,而是区分三类动作:

动作 适用场景 推荐设计
审批意见 审批人判断通过/拒绝 审批节点只写意见、签名、审批附件,不改主数据
补充资料/办理任务 流程中某个角色需要补材料,如负责人上传清单 建模为“办理/填写任务节点”,只开放指定字段
驳回修改 申请单核心内容有误,需要发起人或指定角色修改 回退到“修改节点”,使用专门的修改视图

驳回修改提供两种模式:

  1. 内嵌修改模式:适合低代码表单、字段少、无复杂事务。用户在待办的“修改任务”里直接编辑允许字段,点击“保存并重提”,系统保存业务数据、更新流程变量、完成修改节点。
  2. 跳转业务表单模式:适合采购合同、订单、库存、价格测算等复杂代码业务。待办里展示驳回原因和“去业务单据修改”按钮,打开业务模块自己的编辑页;业务页保存后调用 BusinessFlowGateway.resubmit(...) 完成修改节点。

默认建议:

  • 低代码对象使用内嵌修改模式。
  • 代码优先复杂业务使用跳转业务表单模式,除非业务模块提供了可安全嵌入的 BUSINESS_CODE_FORM 修改视图。
  • 驳回时必须明确目标:退回发起人、退回上一节点、退回指定办理节点。不要把“拒绝终止”和“退回修改”混成一个按钮。

最终推荐口径:

审批节点:默认只读业务主数据,只写审批意见/审批附件。
办理节点:按节点字段权限补充指定业务字段,如负责人上传清单。
驳回修改节点:低代码简单表单可在待办中内嵌修改;复杂代码业务默认跳回业务单据页修改。

8. 前端设计

8.1 设计器主链路

对象设计器建议调整为一条流程类应用搭建向导:

  1. 表单创建:字段、布局、校验、联动、公式。
  2. 单据生命周期:状态字段、编号、发起人、负责人、编辑/删除/发起策略。
  3. 流程配置:选择模板或已有流程,配置变量映射、标题、发起方式。
  4. 节点表单权限:每个审批节点选择表单资产、表单视图和字段权限。
  5. 自动化:流程通过/驳回/撤回后的触发器、消息和关联记录动作。
  6. 权限:菜单、行操作按钮、数据权限、审批角色可见性。
  7. 发布检查:一次性检查表单、状态、流程、变量、权限、触发器。

8.2 待办审批页

待办页优先渲染:

TaskFormInfo.formType = BUSINESS_OBJECT_FORM
TaskFormInfo.formType = BUSINESS_CODE_FORM

页面布局:

  • 左侧:业务数据表单,只读/可编辑由节点字段权限控制。
  • 右侧:审批记录、流程图、当前节点信息、审批动作。
  • 底部:通过、驳回、退回、转办、撤回等动作。

不再要求每个流程都写一个外部审批表单页面。 复杂代码业务如果选择 BUSINESS_PAGE_MODIFY,待办页左侧展示只读摘要和驳回原因,提供“去业务单据修改”动作;业务页保存后调用重提接口。

8.3 运行态详情页

继续复用 AiCrudPage + AiCrudFlowDetail

  • 业务数据 Tab。
  • 流程进度 Tab。
  • 触发器/消息日志可以作为后续扩展 Tab。

9. 流程模板库

模板不只是 BPMN XML,还应包含变量、节点权限和检查规则。

模板 适用场景 默认能力
serial_approval 普通串行审批 发起人 -> 审批人 A -> 审批人 B -> 结束
countersign_approval 多人会签 multiInstanceLoopCharacteristics,全部通过才完成
parallel_or_approval 并行或签 多分支任一通过即进入结束路径
reject_modify_resubmit 驳回修改重提 固定 initiator_modify_task,重提复用原实例
approval_with_cc 审批后抄送 流程通过后由 Flow 统一抄送
approval_post_action 审批后处理 通过后触发 FLOW_APPROVED 自动化

节点命名建议:

start_event
submit_task
dept_manager_task
finance_task
initiator_modify_task
cc_task
end_event

10. 发布检查

发布前必须检查:

  • 业务对象已发布或可同步发布。
  • 单据模式启用时,状态字段存在且有状态映射。
  • allowStartFlow=true 的状态至少一个。
  • 流程模型存在且已发布。
  • 变量映射源字段存在。
  • BPMN 中引用的变量要么由系统变量提供,要么由变量映射提供,要么由默认值/表达式提供。
  • 业务相关审批人变量不得由 BPMN 直接查询业务表。
  • 节点表单权限引用字段存在。
  • 节点 formRef 引用的表单资产存在,且资产类型与运行时能力匹配。
  • 代码表单资产必须提供字段目录;复杂区块至少提供虚拟字段/区域目录。
  • 外部 URL 表单只能在高级模式配置,并提示无法参与字段级权限校验。
  • 驳回修改策略配置了 modifyTaskKey,且 BPMN 存在该节点。
  • 驳回修改模式必须明确是 INLINE_MODIFY 还是 BUSINESS_PAGE_MODIFY
  • START_FLOW 按钮权限存在。
  • 触发器动作引用的目标对象、字段、消息通道存在。
  • 运行数据源可用,主键字段可解析。

11. 可观测性

新增统一 trace 维度:

correlationId = flowStart:{tenantId}:{businessKey}:{timestamp or snowflake}

链路日志至少覆盖:

  • 发起请求来源:手动按钮、触发器、FlowEntry。
  • 业务记录快照和变量快照。
  • FlowClient 请求与返回。
  • ai_business_flow_instance_link 写入。
  • Flow 事件接收和幂等判断。
  • 状态回写前后值。
  • 业务事件发布。
  • 触发器执行。
  • 消息推送。

可先落在 ai_business_trigger_log 或新增轻量 ai_business_flow_trace_log,后续再接入监控页面。

12. 安全与权限

  • 流程发起必须校验按钮权限和单据状态,前端禁用只作为体验层。
  • 待办审批页业务详情必须校验当前用户是当前任务处理人、候选人、抄送人、发起人或具备业务详情权限。
  • 节点字段权限由后端输出,前端只负责渲染,不作为安全唯一依据。
  • 业务状态回写使用内部方法,禁止走普通用户可调用的动态 CRUD 更新接口。
  • API Key、外部消息通道密钥不能进入流程变量和前端响应。
  • 跨数据源业务记录和 Flow 状态不做分布式强事务,采用幂等事件和补偿。

13. 迁移策略

13.1 对已有低代码对象

  • 保留现有 ai_business_bindingai_business_document_config
  • 首次打开流程配置时,将旧字段归一化为 BusinessFlowContract
  • 保存时继续写兼容字段:flowModelKeytitleTemplatestartModevariableMapping
  • 发布时生成契约快照。

13.2 对已有流程实例

  • 保留 recordId 读写。
  • 新增 recordKey 后,用 recordId 回填字符串值。
  • 运行中流程继续按启动时 flowModelKey 和实例关联处理,不受新设计态变更影响。

13.3 对手写业务模块

  • 保留 @FlowBind/@FlowCallback 能力作为兼容层。
  • 新复杂业务优先实现 BusinessFlowAdapter 并注册到 BusinessFlowAdapterRegistry
  • 手写模块保留自己的实体、Mapper XML、Service、事务和状态机,不迁移到动态 CRUD。
  • 手写模块通过 BusinessFlowGateway 发起流程,通过 BusinessFlowEventBridge 接收事件。
  • 如果待办页要展示专属复杂业务表单,Adapter 返回外部详情路由或 BUSINESS_CODE_FORM 上下文。
  • 平台统一提供流程实例关联、trace、消息、流程历史和验收模板。

14. 风险

风险 影响 处理
自定义主键未贯通 低代码多库对象无法发起流程 recordId Long 升级为 recordKey String,保留兼容字段。
Flow 事件乱序或重复 状态被错误回写 引入 eventId/correlationId/last_event_time 和幂等表/字段。
设计态变更影响运行中实例 审批页表单和变量错位 启动流程时固化契约版本和表单快照。
跨库无分布式事务 发起成功但状态未回写 使用本地事务 + 幂等补偿 + 可重放 trace。
待办页绕过业务权限 敏感数据泄露 后端输出表单上下文时校验 taskId、任务状态、当前办理人、流程实例、业务 Key 和节点 Key;保存和重提必须由已签收办理人执行。
BPMN 模板表达力不足 复杂流程仍需手工 模板覆盖高频场景,保留 Flow 设计器高级模式。

15. 结论

参考文档提出的优化方向合理,但在 Forge 中不能停留在“每个业务 Service 继承一个抽象类”。Forge 当前已经有低代码运行时和业务应用平台,正确的落地方式是:

  1. 以业务对象为中心沉淀 BusinessFlowContract
  2. BusinessFlowGateway 统一手动、触发器、流程入口三类发起方式。
  3. BusinessFlowEventBridge 消费 Flow 全量事件,统一状态回写和副作用。
  4. BUSINESS_OBJECT_FORM 打通待办审批页和低代码业务表单。
  5. 以发布检查和模板库把“表单创建 -> 流程配置”变成低代码完整链路。

这样既能解决当前“业务模块与流程模块耦合严重、新增流程多处修改、复用性低”的痛点,也能支撑长期流程类低代码应用搭建。