表单设计与运行时
工作流表单用于收集流程变量、渲染审批详情和驱动分支/审批人解析。当前引擎支持三种表单来源,并提供远程数据源增强表单选项;对外部系统的统一外呼配置见连接器。
表单来源
| 类型 | 数据归属 | 说明 |
|---|---|---|
designer 表单库设计器 | workflow_instances.formData | 通过「表单库」维护可复用表单,流程定义绑定 formId |
custom 自定义业务表单 | workflow_instances.formData | 通过 React 组件承载复杂交互,提交值仍进入流程实例 |
external 业务系统主导 | 业务模块自己的表 | 流程保存 bizType + bizId 和路由变量;业务表单同时展示流程预览或实际审批信息,审批详情中的业务资料由查看组件渲染 |
表单库
「工作流引擎 → 流程管理 → 表单库」支持表单分页列表、启停、创建、编辑、复制和删除。流程设计器选择表单后,发起工作台、审批页和实例详情都使用同一套内置渲染器。
表单更新携带乐观锁版本号 revision:保存时回传 expectedRevision,与服务端当前版本不一致返回 409,编辑器提示加载最新内容,避免多人同时编辑互相覆盖。
字段标识(key)重命名会自动级联:除表单内部引用(显隐/必填/只读规则、级联、天数联动、公式、比较校验)外,保存时还会把重命名映射发给服务端,重写所有引用该表单的流程定义 flowData 中的分支条件、字段权限、审批人字段(formUser/formDepartment)、触发器模板({{form.字段}})、子流程映射、摘要字段和编号规则的参数映射(formData.字段)。已发布版本快照与历史实例保持冻结不变。
字段类型
| 分组 | 字段 |
|---|---|
| 基础控件 | 单行文本、多行文本、数字、金额、日期、日期区间、时间 |
| 选择控件 | 下拉单选、下拉多选、自动完成、单选框组、复选框组、开关、滑块、级联选择、标签、颜色 |
| 格式化控件 | 手机号、邮箱、身份证、网址、密码、验证码、评分、NPS 量表、矩阵量表、公式 |
| 系统组件 | 人员选择、部门选择、字典选择、关联审批单 |
| 高级控件 | 附件、图片、省市区、定位、手写签名、富文本、明细 |
| 布局控件 | 说明文字、流水号、分栏、分割线、分组、标签页、分步 |
附件与图片字段在发起、审批可编辑场景中通过 POST /api/workflows/attachments 上传:按工作流身份(可发起或可审批任一权限)放行,执行统一大小上限与 magic bytes 真实类型校验,落入受管文件并记录工作流审计。字段可配置数量上限、单文件大小与类型(accept)。
字段可配置必填、默认值、默认值公式、占位提示、帮助文本、长度、正则、数值范围、日期限制、文件限制、选项颜色与配图、动态可见、动态必填、动态只读、字段比较、自定义校验公式、明细列唯一和公式表达式。显隐/必填/只读规则组支持嵌套子组(如「A 且 (B 或 C)」),前端渲染与服务端校验同源求值。
签名字段
手写签名字段使用 type='signature',策略独立于「是否必填」:
signaturePolicy | 填写方式 |
|---|---|
reusable(默认) | 可以本次手写,也可以确认使用当前账号的已保存签名 |
handwritten | 本次重新手写,不提供个人模板复用 |
未勾选必填的签名字段可以留空。签名控件在分组、分栏、标签页和明细表中同样遵循字段策略;服务端递归校验,不只依赖界面控制。
提交时发送 SignatureInput,服务端生成 SignatureSnapshot 后保存到对应表单字段。草稿中与数据库同一路径既有快照完全相同的值可以保留,修改后的值必须重新提交签名输入;克隆/重新发起为新申请时清空旧签名。详情与打印只读取已保存快照,个人模板更新、删除不影响旧单据。
个人模板管理与输入结构见个人中心与我的签名。演示表单「个人签名复用示例表」和「本次手写签名示例表」分别验证两种策略;对应审批模板的使用步骤见流程模板。
共享 WorkflowFormRenderer 的业务契约由 signatureMode 显式选择:工作流入口使用 workflow 模式(SignatureInput/SignatureSnapshot 与个人签名);报表填报、公开填报和会员填报使用 image 模式(纯 PNG、本次手写,不调用管理员个人签名接口)。这是两个业务域各自的当前契约。
设计器操作
- 画布所见即所得:画布按字段配置渲染真实控件外观与 24 栅格并排布局,与填写页一致(超过 80 个字段自动降级简洁模式);分栏支持拖拽分隔线调列宽(双击均分);容器支持有限嵌套(分栏列内放分组/明细、分组内放分栏/明细,深度 ≤ 3)。
- 画布交互:字段右键菜单(上移/下移/复制/粘贴/创建副本/必填切换/存为模板/删除)、键盘操作(
Ctrl+C/V复制粘贴、Delete删除、↑/↓切换选中、Esc取消、Ctrl+Z/Shift+Z撤销重做)、多选(Ctrl 点选 / Shift 范围)批量删除、批量宽度/必填/只读、合并为分栏;拖拽支持边缘自动滚动、插槽指示与浮签。 - 大纲树:左侧面板「大纲」页展示字段嵌套结构,点击定位画布并选中。
- 防丢失:编辑内容自动本地暂存(3 秒防抖),意外关闭后重新打开提示恢复草稿;保存前可查看变更摘要(新增/删除/重命名/修改明细)。
- 历史:撤销/重做外提供历史步骤面板,点击任意步骤直接跳转。
- 模板:工具栏「模板」支持插入常用字段组,或打开表单模板库(请假/报销/采购/入职/出差/合同等完整模板,预览后一键应用,可撤销);任意字段可右键「存为我的模板」保存到本地,在控件面板「我的模板」中复用。
- 控件搜索:控件面板按名称 / 类型标识 / 说明过滤,支持拼音首字母与全拼(如
dhwb、xiala),与顶部菜单搜索、偏好设置搜索同一口径。 - 配置面板:校验/显隐 Tab 带「已配置」圆点;支持配置项关键词搜索(同样支持拼音)快速跳转;选项类字段支持批量文本模式(
值|显示名多行粘贴)与选项配图。 - 明细表:填写时支持行复制与「从剪贴板粘贴」(Excel 多行粘贴自动按列解析、数字类型自动转换);子列可配置固定列宽、行内公式(引用同行列自动计算)、行内显隐与行内校验公式。
- 联动赋值:静态选项映射之外,绑定远程数据源的下拉支持按选中记录回填其它字段(配置目标字段 → 数据源记录字段映射)。
表单运行时与服务端校验
显隐规则、条件必填等运行时求值逻辑统一收敛在 @zenith/shared/workflow 的 form-runtime.ts 中,前端渲染器与服务端同源引用,避免两端行为漂移:
- 发起与提交草稿:服务端按表单快照强制执行全量规则校验——必填(含条件必填)、文本长度、正则、数值范围、日期可选范围、跨字段比较、自定义校验公式、明细行级(行必填/列唯一/行内校验公式),并遵循显隐联动与发起节点(
start)字段权限——被隐藏或只读的字段不参与校验,越权提交的字段值被丢弃。公式求值统一使用 同域的formula.ts(与前端实时计算同一引擎)。 - 定时发起与自动化发起:沿用宽松语义,不强制必填。
- 实例详情:
formData按查看者身份脱敏——发起人按start节点权限、参与人按其任务节点权限并集过滤hidden字段;监控管理员与超管不脱敏;未配置字段权限时不额外过滤表单字段。
公式字段
公式字段使用 {字段key} 引用字段值,使用 {明细key.列key} 引用明细列聚合。支持数学、逻辑、文本、日期函数,例如:
IF({days}>3, {amount}*0.9, {amount})
SUM({items.amount})
DATEDIF({start}, {end}, "d")公式编辑器支持在光标处点选插入字段引用(含明细列)与函数片段,并提供实时试算:为每个引用填入样例值即可即时查看计算结果。函数覆盖数学/逻辑/文本/日期与查表格式化(NETWORKDAYS 工作日、DATEADD 日期加减、LOOKUP 查表、FORMAT 千分位、ISEMPTY 判空等)。表单体检会检测公式、天数联动与联动赋值之间的循环依赖(如 A 公式引用 B、B 公式又引用 A),存在循环时按错误阻断保存。
字段在流程中的作用
| 场景 | 说明 |
|---|---|
| 条件分支 | 使用表单字段和聚合值计算分支命中 |
| 审批人解析 | formUser 读取人员字段,formDepartment 读取部门字段并解析负责人 |
| 表单权限 | 节点按字段设置只读、可编辑、隐藏 |
| 路由分支 | 规则中心决策表、评分卡或决策流 outputs 会合并进 formData,可作为后续字段变量使用 |
| 子流程映射 | 父流程字段映射到子流程,子流程输出回填父流程 |
| 触发器模板 | {{form.field}} 占位符渲染请求体、更新字段或回调参数 |
变量与表达式语法
各场景有自己的求值语法,配置时按对应编辑器使用:
| 场景 | 语法 / 作用域 | 规则 |
|---|---|---|
| 表单公式 | {amount}、{items.amount} | 引用字段或明细聚合,使用表单公式函数 |
| 条件与审批人表达式 | form、starter | 读取表单与发起人上下文,使用安全表达式求值 |
| 触发器 / 补偿模板 | {{form.amount}} 及各节点提供的额外变量 | 按节点文本模板渲染,URL 占位值按百分号编码 |
| 流程自动化 | {{system.title}}、{{formData.amount}} | 完整变量引用保留原始 JSON 类型,嵌入文字时转为文本 |
| 定时发起标题 | {{date}}、{{datetime}} | 根据计划时刻生成标题 |
| 业务编号 | {SEQ:4}、{FORM.采购类型}、{categoryCode} 等 | 在编号规则中心配置;可组合多个表单字段,流程发布时固定规则版本与字段来源 |
模板变量的完整说明见触发器与外部审批、流程自动化、定时发起及流程定义设置。
自定义业务表单
custom 表单适合表单库控件无法覆盖的交互。流程定义保存组件路径和变量声明,运行时通过 BusinessFormHost 加载。
| 配置 | 说明 |
|---|---|
| 创建 / 填写组件 | 相对 packages/web/src/pages 的组件路径 |
| 查看组件 | 可选;为空时复用创建组件并以只读模式渲染 |
| 图标 | 用于业务表单入口展示 |
| 变量 | 声明可被条件分支和审批人解析读取的字段;key 须以字母/下划线开头、仅含字母数字下划线且不可重复(面板内联校验) |
业务组件接收 mode、container、definitionId、instanceId、value、readOnly、variables 和 getFormApi。在发起和审批可编辑场景中,组件需通过 getFormApi 暴露 validate() 与 getValues()。
运行时行为:
- 发起:
mode='create',草稿编辑时以value回填已保存的 formData;「存草稿」优先经getValues()直取当前值(不校验,与服务端草稿宽松语义一致),正式提交仍执行validate()全量校验。 - 审批:当前处理人所在节点存在权限为「编辑」的变量时,以
mode='approve'可编辑渲染,审批提交时按 edit 白名单收集变更合并进实例 formData(服务端sanitizeFormUpdatesByNodePerms双重过滤);否则以mode='view'只读渲染。 - 发布门禁:创建组件(及填写了的查看组件)路径必须能在
src/pages下解析,变量声明 key 须完整合法,否则阻断发布并跳回「表单」步骤。
业务系统主导表单
external 表单用于已有业务实体接入审批。业务数据保留在业务表中,工作流实例只保存业务键和少量路由变量。完整接入方式见 业务模块接入工作流。
- 此类型仅需配置审批查看页组件(创建页输入已隐藏)。该组件只渲染业务资料,不包装抽屉或重复添加审批链;流程信息由公共流程容器承载。
- 审批容器中的业务资料恒为只读,节点「表单权限」的编辑列被禁用;业务模块自己的新增/草稿编辑表单仍按业务状态和权限编辑。业务编辑入口接入
BusinessWorkflowPanel,提交前预览链路,提交后原地展示实际流程。 - 查看组件使用
bizId + instanceId调用业务approvalDetail;指定实例必须关联该业务并对当前查看人可见。切换往次审批只切换流程记录,业务资料仍为当前值,界面明确提示。 - 发起守卫:节点按
formUser/formDepartment解析审批人且未配置空审批人兜底策略时,对应路由变量缺失会阻断发起并返回明确错误,避免节点被默认「自动通过」静默跳过。 - 业务键(
bizType + bizId)的发起去重口径为活跃实例(草稿/运行中/挂起/退回待重提);流程终态(通过/驳回/撤回/取消)后,业务记录可修改后重新发起新流程。
另外,在设计器「表单」步骤切换表单类型时,若已有表单绑定或业务表单配置,会弹出确认提示:保存后另一族配置将被清空,基于原字段(变量)的分支条件、审批人与字段权限需重新检查。designer 类型发布时还会校验:流程引用了表单字段却未绑定表单、或绑定表单已停用/被删除,均阻断发布。
审批查看态中的公式、金额和普通字段以可选中文本展示;明细使用可横向滚动的文本表格,支持复制明细、枚举标签和汇总。查看已有实例时使用已保存的公式结果,不因打开详情重新计算历史值。只有当前有编辑权限的字段保留输入控件,隐藏值不进入复制内容与可见汇总。
远程选项与联动
下拉与自动完成字段可引用已启用的数据源拉取选项,也可按选中记录回填其它字段。登记、加密请求头、响应映射、运行时代理与缓存说明见远程数据源。
流水号控件只读展示当前流程实例的业务编号,不能设置独立前缀或提交字段值。草稿显示「正式提交后生成」,首次提交由服务端分配,退回重提沿用原编号;嵌套布局与审批详情使用同一实例编号。