当前 Web 已提供全页流程设计器,不再要求作者直接维护整段 JSON。画布只是编辑器,服务端仍是节点能力、业务元数据、草稿修订、校验和发布的权威来源。浏览器里的崩溃恢复快照不会取得发布权,也不能替代数据库草稿。
1. 设计器数据流
设计器只消费 @bitz/platform-sdk。节点类型、字段 widget、枚举、目录数据源和表达式上下文来自后端契约,前端本地模型负责把它们投影为可编辑控件。
2. 当前端点
| 方法与路由 | 用途 | 权限 |
|---|---|---|
GET /api/workflow/definitions/designer-schema | JSON Schema、七类节点和字段元数据 | definition read |
GET /api/workflow/metadata/bindable-entities | 可绑定业务实体 | workflow.metadata.read 或隐含授权 |
GET /api/workflow/metadata/entities/{entityName}/flow-fields | FlowScope 字段目录 | workflow.metadata.read 或隐含授权 |
GET/PUT/DELETE /api/workflow/definitions/{key}/draft | 读、保存、删除草稿 | read / update / delete |
POST /api/workflow/definitions/{key}/draft/validate | 校验已保存的精确修订 | verify |
POST /api/workflow/definitions/{key}/draft/simulate | 按变量模拟精确修订 | use |
POST /api/workflow/definitions/{key}/draft/publish | 校验后创建不可变版本并更新部署绑定 | publish |
GET /api/workflow/definitions/{key}/versions | 版本坞列表 | read |
GET /api/workflow/definitions/versions/{definitionId} | 读取不可变版本 | read + authoring scope |
workflow.definition.manage 隐含 create/update/delete/publish/verify/use,但故意不隐含 read。workflow.definition.create 会隐含 update,使只授予 create 的角色能够保存 revision=0 的新草稿。完整作者角色仍应显式同时具备 read 和写入能力。
3. 服务端 Schema
WorkflowDesignerSchema 返回权威 JSON Schema、当前 Host 注册的节点类型、参与人 Resolver、服务任务 Handler、表达式内置变量、Timer action 与 Listener type。每个配置字段可声明:
ValueType、Required、Description、Section 和 Order;- Widget,例如
participantBuilder、multiInstanceBuilder、rollbackBuilder、formFieldBuilder、dataScopeBuilder、timerBuilder和listenerBuilder; - EnumValues、嵌套 Properties、数组 ItemSchema;
- DataSource 与 ExpressionContext。
服务任务 Handler 目录当前允许为空;UI 应显示空目录并保留受控输入,不能假造未注册实现。旧客户端可以忽略新增元数据,但不得把自己的节点白名单当成发布安全边界。
4. AOT 业务实体目录
可绑定实体不是运行时反射扫描结果。WorkflowBusinessMetadataProjector 从编译期 EntityMetaModel 读取 [BitzWorkflow(processKey)],按类型短名输出 EntityName、ProcessKey、DisplayName 和 Category。
字段目录只公开设置了 FlowScopeDisplayName 的列,并可带 Group、IsReadOnly、FieldDataType、DataSourceKey、IsRequired 与 MaxLength。元数据缺失、实体未知或目录为空时返回空集合,不升级为 500。
// ① ProcessKey 成为设计器可建议的稳定流程键。[BitzWorkflow("matter-intake", DisplayName = "立案审批", Category = "Litigation")]public sealed class MatterIntake : TenantAggregateRoot<string>{ // ② 只有显式声明 FlowScope 的字段进入表单字段目录。 [BitzFlowScope("争议标的金额", Group = "案件要素", IsReadOnly = true)] public decimal DisputeAmount { get; private set; }}具体 Attribute 参数以当前 BitzWorkflowAttribute / BitzFlowScopeAttribute 定义为准。新增元数据后必须重新构建并导出 OpenAPI/前端合同,不能靠热加载反射发现。
5. businessBinding DSL
定义根可写:
{ "key": "matter-intake-approval", "businessBinding": { "entityName": "MatterIntake" }, "nodes": [ { "id": "partner", "type": "userTask", "name": "主办合伙人审批", "formFields": [ { "fieldName": "DisputeAmount", "visibility": "readOnly" }, { "fieldName": "ApprovalComment", "visibility": "editable" } ] } ], "edges": []}EntityName 使用编译期目录中的类型短名。设计器变更绑定时保留 businessBinding 的未知扩展字段;清空 EntityName 才移除整个绑定对象。
6. formFields 的实际边界
formFields 是每个 UserTask 的表单字段策略矩阵。设计器把已有 DSL 与 FlowScope 目录合并,当前只支持 editable、readOnly、hidden 三种可见性。字段是否必填来自 FlowScope 元数据的 IsRequired,不属于 formFields DSL。
当前 Validator 在元数据可用时检查 EntityName 和 fieldName,但未知项只产生 warning,不阻断发布。这是兼容旧定义和跨版本部署的选择,不代表运行时自动拥有通用表单引擎。业务页面仍需读取并执行这组策略;不认识的字段必须安全忽略,不能据此绕过业务 owner 的字段授权。
7. 草稿与乐观并发
保存请求携带 Key、Name、JsonDefinition、可选 BaseDefinitionId、ExpectedRevision 和 DesignerStateJson。创建使用 revision 0;更新必须提交最近一次响应的 Revision。服务端验证 Key、名称、JSON 根、定义内 Key、基线可见性和设计器状态大小后再保存。
两个标签页同时编辑时,后保存者不会覆盖新修订,而是收到 revision conflict。客户端应提示重新加载或人工合并,不要自动用本地快照强制覆盖。
8. 浏览器崩溃恢复
前端会把 dirty draft 和画布状态保存为本地恢复快照。它只用于浏览器崩溃或意外关闭后的体验恢复:
- 存储 key 目前只包含租户和 definition key,不包含用户标识;同租户多人共用同一浏览器配置文件时可能互相覆盖或看到恢复草稿;
- 解析失败或快照版本不符时丢弃;服务端 Revision 更新后,旧 baseline 快照也不会被提示恢复;
- 恢复后仍必须以服务端 Revision 保存;
- Token、权限、TenantId 决策和发布状态不进入快照。
因此共享工作站必须使用独立操作系统账号或浏览器配置文件,并在登出时清除本地恢复数据。当前实现没有按时间淘汰快照,也没有把用户 ID 纳入 key;如果部署场景允许多人复用同一浏览器配置文件,应先补上这两项隔离措施。
9. 权威校验
草稿校验由 ValidateWorkflowDefinitionDraft 按 Key 与 ExpectedRevision 重新加载权威草稿,再调用引擎校验。发布命令重复执行同一校验;出现 Error issue 时返回结构化 Validation 且 Published=false,不会创建版本或切换部署。
基础校验覆盖节点 ID、悬空边、自环、开始/结束、入出线、网关条件、参与人和可达性。未知业务绑定与表单字段是 Warning;某些任务开关、Timer 动作和表达式静态类型仍需业务测试证明。
10. 模拟路径
模拟响应现在包含 PathNodeIds 与 VisitedEdgeRefs,前端据此高亮画布路径。它不写数据库、不触发 Listener、不创建 Task,遇到 UserTask 就停止,最大深度 100。
排他与包容网关预览都只选择第一条命中边;并行网关也只展示第一条路径。因此一次绿色高亮只证明这组变量的预览结果,不证明并行汇聚、多人任务或持久化执行正确。
11. 版本坞与租户作用域
Host 作者使用 PLATFORM 作用域;租户作者使用有效 TenantId。版本列表先查当前创作作用域,租户没有自己的版本时才回退平台默认版本。Host 不会回退到任意租户版本。
按 DefinitionId 读取版本时,Handler 再做可见性检查:Host 只能读 PLATFORM;租户可读本租户与 PLATFORM 基线;越权统一返回 NotFound,避免利用 ID 探测其他租户 DSL。创建基于版本的 fork 也执行同样的基线归属校验。
12. 发布语义
设计器使用 /draft/publish:它验证修订、执行权威校验、创建或复用不可变版本,验证 DefinitionId/Version/Checksum,再仅在绑定变化时更新 tenant/office deployment。
仓库仍保留直接 POST /api/workflow/definitions/ 的管理端部署入口;该旧入口只要求 JSON 可编译,不替设计器执行完整 validate。自动化调用它时必须先显式调用 /validate,新 UI 应优先使用 draft publish 闭环。
13. 前端权限与错误
按钮应按后端动作分别授权:保存 update/create,校验 verify,模拟 use,发布 publish,删除 delete。不要因为用户能编辑就默认能校验或模拟。
Validation issue 要按 NodeId/EdgeRef 定位画布,Warning 与 Error 分开显示。网络失败、409 修订冲突和授权 403 也不能合并成“保存失败”,否则作者无法判断是否可以安全重试。
14. 验证命令
# ① 后端:Schema、AOT 元数据、草稿动作、作用域和模拟路径。dotnet test tests/BitzOrcas.Unit.Tests \ --filter "FullyQualifiedName~WorkflowBusinessMetadata|FullyQualifiedName~DefinitionSimulator"dotnet test tests/BitzOrcas.Application.Tests \ --filter FullyQualifiedName~Workflow
# ② 前端:恢复、Builder、路径高亮与全页路由。cd frontendyarn workspace @bitz/app test workflow-designer-recovery workflow-builder-models workflow-definition-runtime navigation-contract15. 发布检查
- Schema 与前端 widget 的未知值均安全降级;
- AOT 元数据只公开 owner 明确标注的实体和字段;
- create/update/read/verify/use/publish/delete 权限组合经过正反测试;
- 跨租户 DefinitionId 和 Host PLATFORM 版本列表有回归测试;
- crash snapshot 不含凭据;共享浏览器场景另行验证用户隔离与过期清理;
- Error 阻断发布,Warning 有明确接受或修复记录;
- 模拟路径只作为预览证据,真实执行仍覆盖双 ORM、并发和故障恢复。