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
参考文档 /Users/yaomindong/Desktop/project/mdframe/shenrong/shenrong-projman/code-copilot/knowledge/business-flow-fast-adaptation-guide.md 的核心判断是:
flow 管通用流转,business 管业务规则
这个方向与 Forge 当前架构决策一致:审批不再建设独立审批引擎,统一归入 Flowable 流程引擎;低代码业务对象已经围绕“表单优先、动态 CRUD、单据配置、流程绑定、触发器、消息、报表”形成主链路。
但 Forge 不是传统手写业务系统。当前工程已经具备:
BusinessFlowService 动态发起流程、写入 ai_business_flow_instance_link、回写单据状态。因此参考方案里“新增 BusinessFlowAdapter + AbstractBusinessFlowService”不能原样作为主方案。它适合手写业务模块,但对 Forge 低代码平台来说,应升级为:
业务对象流程契约 + 运行时流程网关 + 流程事件桥 + 低代码发布编译
目标不是让每个新流程少写几个 Service 方法,而是让低代码用户完成:
表单创建 -> 单据生命周期 -> 流程配置 -> 节点表单/权限 -> 发布检查 -> 运行态填报/审批/回写/消息
BusinessFlowService 已承担低代码业务对象与流程引擎的动态集成。
ai_business_binding 读取 binding_type=FLOW 配置。FlowClient.startProcess 发起流程。ai_business_flow_instance_link。BusinessDocumentRuntimeService 已把单据状态、流程实例、可执行动作合并为运行态协议。
AiCrudPage 可根据运行态动作显示“发起主流程”。Flow 侧已经具备事件发布和租户上下文能力。
FlowTaskEventListener 发布 TASK_CREATED、TASK_COMPLETED、PROCESS_COMPLETED、PROCESS_REJECTED、PROCESS_CANCELED。FlowEventMessage 已携带 tenantId、businessKey、processInstanceId、processDefKey、taskDefKey、variables 等关键字段。FlowEventSubscriber 收到事件后会用 TenantContextHolder 分发。低代码设计器已经具备流程配置入口。
BusinessDocumentPanel 配置单据模式、编号、状态映射、流程展示开关。BusinessFlowBindingPanel 配置流程模型、发起方式、标题模板和变量映射。FlowVariableMappingEditor 支持推荐映射。Flow 入口表单也能反向创建低代码业务记录。
FlowBusinessObjectRuntimeAdapterImpl 支持 BUSINESS_OBJECT/HYBRID 数据模式。集成层协议偏薄。
两条链路尚未统一。
ai_business_flow_instance_link,但记录主键、变量快照、状态机、表单快照和回调语义没有统一契约。事件消费不适合动态低代码主流程。
FlowEventSubscriber 面向 @FlowBind(modelKey=...) 的手写 Bean 分发。@FlowBind Bean。BusinessFlowEventBridge 订阅所有 Flow 事件,再按 businessKey/objectCode/processDefKey 路由到低代码对象。记录主键协议不够通用。
BusinessFlowStartDTO.recordId、AiBusinessFlowInstanceLink.recordId、TaskFormInfo.recordId 和 FlowBusinessObjectRuntimeAdapter.BusinessRecordCreateResult.recordId 当前是 Long。驳回修改重提没有产品级协议。
BusinessFlowService.normalizeCallbackResult 只按最终结果回写 APPROVED/REJECTED/CANCELED,缺少 TASK_COMPLETED + approvalResult=reject + modifyTaskKey 的中间状态处理。审批办理页与业务详情页仍会分叉。
TaskFormInfo 支持动态表单、外部表单、表单快照和字段权限。AiCrudPage/AiForm/FieldValueRenderer。BUSINESS_OBJECT_FORM 表单类型来复用业务对象详情/编辑渲染和字段权限。发布检查与流程配置还不够一体化。
可观测性和验收模板不足。
correlationId 串起来。| 参考建议 | 判断 | Forge 落地方式 |
|---|---|---|
flow 管通用流转,business 管业务规则 |
直接采纳 | Flow 只负责模型、实例、任务、事件;业务对象负责状态字段、变量、数据权限、副作用。 |
抽 BusinessFlowAdapter |
改造采纳 | 手写业务模块可用 Adapter;低代码主链路应以 BusinessFlowContract + BusinessFlowGateway 替代每业务 Service 继承。 |
| 建业务流程元数据配置 | 直接采纳但复用现有表 | 复用 ai_business_binding、ai_business_document_config、ai_business_flow_instance_link,补充发布态契约快照,不另起重复配置表。 |
| 流程模型关联业务表并配置状态字段 | 分层采纳 | 这是最小可用集成层,适合低代码对象和简单业务表;Forge 需要扩展为 businessBinding,同时保留复杂代码业务 Adapter。 |
统一事件协议携带 tenantId/businessKey/processInstanceId/taskDefKey/variables |
直接采纳 | 现有事件字段基本具备;补 eventId、correlationId、objectCode、recordKey、taskResult、formInstanceId。 |
| BPMN 模板库 | 直接采纳 | 接入 Flow 设计器和 AI 生成器,模板产出 BPMN、变量清单、节点表单权限默认值和发布检查规则。 |
| 驳回修改重提固化为框架能力 | 直接采纳 | 作为 rejectStrategy=RETURN_TO_MODIFY_TASK 的契约能力,不要求每个业务对象手写逻辑。 |
| 流程脚手架 | 改造采纳 | 对代码生成模块生成手写业务骨架;对低代码对象生成运行态契约和流程模板,不生成大量重复 Java。 |
| 每条流程手动写 Flyway、菜单、权限 | 不作为低代码主路径 | 手写模块仍需要;低代码应用应通过对象发布自动生成菜单、按钮权限和运行态配置。 |
设计态
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
不是所有业务都适合低代码建模。资金、库存、合同、订单、外部系统集成、复杂状态机等代码优先业务,应保留自己的领域模型、数据库表、事务边界和 Service 编排。
这类业务接入流程时遵循:
BusinessFlowGateway、BusinessFlowEventBridge、流程 trace、待办表单上下文和标准验收模板。businessType/objectCode/modelKey/businessKey 规则,避免流程事件无法路由。新增或重构为以下平台服务:
| 服务 | 作用 |
|---|---|
BusinessFlowContractService |
读取/保存/发布业务对象流程契约,兼容现有 ai_business_binding 和单据配置。 |
BusinessFlowGateway |
统一发起、撤回、取消、重提、查询运行态、更新变量,不让页面和触发器直接拼 FlowClient 调用。 |
BusinessRecordRuntimeFacade |
屏蔽动态 CRUD、运行数据源、主键类型、租户、审计字段和内部状态更新。 |
BusinessFlowEventBridge |
订阅 Flow 全量事件,按业务键和流程契约路由到低代码对象。 |
BusinessFlowStateMachine |
将流程事件、节点结果、单据状态映射成可审计的业务状态变更。 |
BusinessTaskFormContextService |
为待办页输出低代码业务表单上下文、字段权限和审批动作策略。 |
BusinessFlowTraceService |
记录发起、回调、状态回写、触发器和消息的链路日志。 |
BusinessFlowAdapterRegistry |
注册代码优先业务模块的流程适配器,按 businessType/modelKey/businessKey 路由事件。 |
BusinessFormAssetRegistry |
汇聚低代码表单、Flow 动态表单、代码表单和外部表单资产,供设计器选择和待办页解析。 |
发布态应形成一份业务对象流程契约。首期可以存入 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
}
}
类似 JeecgBoot 在流程模型里关联业务表、配置流程状态字段的做法,在 Forge 中可以作为首期最小闭环能力,但要放进业务流程契约,而不是散落在 BPMN 模型属性里。
建议抽象为 businessBinding:
| 字段 | 说明 |
|---|---|
mode |
LOWCODE_OBJECT、BUSINESS_TABLE、ADAPTER |
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 简化模式。统一使用:
${objectCode}:${recordKey}
要求:
objectCode 必须是发布态业务对象编码,不能使用页面临时 configKey。recordKey 首期兼容 Long,后续必须升级为 String,支持自定义单字段主键。BusinessKeyCodec,禁止散落 split(":", 2)。businessKey 不承载租户,租户来自 tenantId 字段和租户上下文。系统变量统一注入:
| 变量 | 来源 |
|---|---|
tenantId |
当前租户 |
objectCode |
业务对象 |
configKey |
发布态动态 CRUD 配置 |
recordKey |
业务记录主键,字符串 |
recordId |
兼容字段,仅 Long 主键时保留 |
businessKey |
${objectCode}:${recordKey} |
startUserId |
发起人 |
startDeptId |
发起部门 |
业务变量来自 variableMapping。业务相关审批人必须在 Business 侧提前解析为变量,BPMN 只消费变量,不直接查业务表。
标准单据状态:
| 标准状态 | 说明 |
|---|---|
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 |
在 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 协议预留,复杂代码业务后续通过注册目录或跳转业务详情页接入,仍不让普通用户手工输入组件路径。不新增重复的“流程业务绑定表”,优先复用:
| 表 | 当前用途 | 目标用途 |
|---|---|---|
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 运行时注册并同步展示 |
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 建议扩展:
schemaVersionrecordKeymainFlowvariableMappingnodeFormseventsoptions后续如需要流程契约版本独立发布,再新增:
ai_business_flow_contract_version
用于锁定“业务对象版本 -> 流程模型版本 -> 表单权限版本 -> 状态映射版本”,避免运行中流程被设计态变更影响。
沿用并增强现有 /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 |
查询表单字段或虚拟区域目录,供节点权限配置 |
| 接口 | 用途 |
|---|---|
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 |
保存当前任务节点授权的业务字段 |
两种方式必须统一到同一个 service:
| 入口 | 场景 |
|---|---|
Redis flow:event:all |
Admin 与 Flow 共 Redis 或分服务部署 |
POST /ai/business/flow/callback |
Flow Webhook 或兼容手动回调 |
内部统一调用:
BusinessFlowEventBridge.handle(FlowEventContext context)
不允许页面、触发器、手写业务 Service 分别实现状态回写。
复杂业务不走低代码对象契约时,提供三种接入方式,按复杂度递进:
| 模式 | 适用场景 | 特点 |
|---|---|---|
| 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 回写状态/执行副作用
设计约束:
onApproved/onRejected/onCanceled 必须幂等。BUSINESS_CODE_FORM 上下文,由业务模块提供只读/编辑组件。当前流程配置里让用户手工输入 formUrl 或组件路径不合理。业务用户不知道表单地址,开发者也容易输入错路径,后续迁移路由时还会造成历史 BPMN 失效。
目标设计是:流程节点不直接保存 URL,而是保存“表单资产引用 + 节点表单策略”。
建立统一表单资产目录,来源可以是低代码、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[],适合不方便加注解的历史模块。流程设计器节点表单配置应展示为选择器:
表单类型:继承业务主表单 / 低代码表单 / 流程动态表单 / 代码表单 / 外部地址
表单资产:采购合同审批表单
表单视图:审批详情 / 负责人补充 / 驳回修改
只有“外部地址”作为高级模式保留手工输入。
每个人工节点保存 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
}
}
字段策略分层:
对于代码表单,字段目录由 BusinessCodeFormProvider.formAssets() 提供。复杂页面如果无法拆成字段,可以把“区域、附件区、操作按钮”抽象成虚拟字段:
baseInfoSection
contractAmount
purchaseListAttachment
riskReviewSection
submitButton
这样流程节点仍能统一控制“哪个节点显示哪个区域、哪个字段可编辑”。
采购合同审批建议拆成几个节点:
| 节点 | 节点类型 | 表单策略 |
|---|---|---|
| 发起节点 | 填报 | 合同基础信息、金额、供应商、附件可编辑 |
| 负责人补充清单 | 办理/填写任务 | 只让负责人编辑 purchaseListAttachment,其他字段只读 |
| 部门负责人审批 | 审批 | 基础信息和清单可见,全部只读,只填审批意见 |
| 法务审批 | 审批 | 合同条款、附件可见,只读,可上传法务意见附件 |
| 财务审批 | 审批 | 金额、付款条款可见,只读,可填财务意见 |
“只有负责人节点显示上传清单”不建议靠不同 Vue 路径解决,而应靠同一个表单资产 + 不同 viewKey/fieldPolicies 控制。这样后续新增节点时不用新增页面。
主流 BPM / 低代码产品的共同思路是“任务绑定表单资产”,而不是让普通用户维护页面路径。Camunda 的 Web Modeler 支持把用户任务链接到同项目表单,并明确推荐 linked form,避免每次变更都复制 JSON;自定义 form key 更偏向外部应用集成。Flowable Form 也以表单 key、字段、outcomes 描述表单定义,任务页展示当前任务对应表单,Save 和 Complete 分离,outcome 变量再驱动后续流转。参考:
因此 Forge 的产品默认策略应是:
formRef,不保存裸 formUrl 作为主配置。保存草稿、完成任务、保存并重提 是不同语义。主流做法不是让任意审批人在任意审批表单里随意修改业务主数据,而是区分三类动作:
| 动作 | 适用场景 | 推荐设计 |
|---|---|---|
| 审批意见 | 审批人判断通过/拒绝 | 审批节点只写意见、签名、审批附件,不改主数据 |
| 补充资料/办理任务 | 流程中某个角色需要补材料,如负责人上传清单 | 建模为“办理/填写任务节点”,只开放指定字段 |
| 驳回修改 | 申请单核心内容有误,需要发起人或指定角色修改 | 回退到“修改节点”,使用专门的修改视图 |
驳回修改提供两种模式:
BusinessFlowGateway.resubmit(...) 完成修改节点。默认建议:
BUSINESS_CODE_FORM 修改视图。最终推荐口径:
审批节点:默认只读业务主数据,只写审批意见/审批附件。
办理节点:按节点字段权限补充指定业务字段,如负责人上传清单。
驳回修改节点:低代码简单表单可在待办中内嵌修改;复杂代码业务默认跳回业务单据页修改。
对象设计器建议调整为一条流程类应用搭建向导:
待办页优先渲染:
TaskFormInfo.formType = BUSINESS_OBJECT_FORM
TaskFormInfo.formType = BUSINESS_CODE_FORM
页面布局:
不再要求每个流程都写一个外部审批表单页面。
复杂代码业务如果选择 BUSINESS_PAGE_MODIFY,待办页左侧展示只读摘要和驳回原因,提供“去业务单据修改”动作;业务页保存后调用重提接口。
继续复用 AiCrudPage + AiCrudFlowDetail:
模板不只是 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
发布前必须检查:
allowStartFlow=true 的状态至少一个。formRef 引用的表单资产存在,且资产类型与运行时能力匹配。modifyTaskKey,且 BPMN 存在该节点。INLINE_MODIFY 还是 BUSINESS_PAGE_MODIFY。START_FLOW 按钮权限存在。新增统一 trace 维度:
correlationId = flowStart:{tenantId}:{businessKey}:{timestamp or snowflake}
链路日志至少覆盖:
ai_business_flow_instance_link 写入。可先落在 ai_business_trigger_log 或新增轻量 ai_business_flow_trace_log,后续再接入监控页面。
ai_business_binding 和 ai_business_document_config。BusinessFlowContract。flowModelKey、titleTemplate、startMode、variableMapping。recordId 读写。recordKey 后,用 recordId 回填字符串值。flowModelKey 和实例关联处理,不受新设计态变更影响。@FlowBind/@FlowCallback 能力作为兼容层。BusinessFlowAdapter 并注册到 BusinessFlowAdapterRegistry。BusinessFlowGateway 发起流程,通过 BusinessFlowEventBridge 接收事件。BUSINESS_CODE_FORM 上下文。| 风险 | 影响 | 处理 |
|---|---|---|
| 自定义主键未贯通 | 低代码多库对象无法发起流程 | 将 recordId Long 升级为 recordKey String,保留兼容字段。 |
| Flow 事件乱序或重复 | 状态被错误回写 | 引入 eventId/correlationId/last_event_time 和幂等表/字段。 |
| 设计态变更影响运行中实例 | 审批页表单和变量错位 | 启动流程时固化契约版本和表单快照。 |
| 跨库无分布式事务 | 发起成功但状态未回写 | 使用本地事务 + 幂等补偿 + 可重放 trace。 |
| 待办页绕过业务权限 | 敏感数据泄露 | 后端输出表单上下文时校验 taskId、任务状态、当前办理人、流程实例、业务 Key 和节点 Key;保存和重提必须由已签收办理人执行。 |
| BPMN 模板表达力不足 | 复杂流程仍需手工 | 模板覆盖高频场景,保留 Flow 设计器高级模式。 |
参考文档提出的优化方向合理,但在 Forge 中不能停留在“每个业务 Service 继承一个抽象类”。Forge 当前已经有低代码运行时和业务应用平台,正确的落地方式是:
BusinessFlowContract。BusinessFlowGateway 统一手动、触发器、流程入口三类发起方式。BusinessFlowEventBridge 消费 Flow 全量事件,统一状态回写和副作用。BUSINESS_OBJECT_FORM 打通待办审批页和低代码业务表单。这样既能解决当前“业务模块与流程模块耦合严重、新增流程多处修改、复用性低”的痛点,也能支撑长期流程类低代码应用搭建。