8.6 KiB
8.6 KiB
OA 条件分支:表单字段驱动可视化配置
日期: 2026-07-15
范围: web-admin 审批设计器步骤 2(表单设计)+ 步骤 3(流程设计);backend 发布校验(引擎匹配逻辑已具备)
Demo: docs/mockups/oa-approval-condition-from-form-demo.html
关联: docs/superpowers/specs/2026-07-14-oa-approval-dingtalk-design.md § 条件分支;backend/app/services/oa_engine.py _match_condition_group
1. 背景与目标
现状问题
流程「条件分支」配置要求用户手写公式,例如 {days} > 5。普通配置者不了解表单字段 field 标识,学习成本高、易配错。
目标
- 在表单设计中显式勾选哪些控件「参与流程条件分支」。
- 勾选后该字段在发起时必填,且必填开关在勾选期间锁定不可关。
- 在流程设计中用可视化规则配置条件:选择字段标题 + 运算符 + 比较值;不提供自定义公式入口。
- 运行时仍用表单填报值做分支匹配,不引入独立的「流程实例变量」配置概念。
非目标
- 系统变量(发起人部门等)进入条件(可二期)。
- 条件组内 OR、跨组复杂布尔、嵌套括号。
- 保留或新增「高级:自定义公式」折叠区(已否定,降低双模式复杂度)。
- 改写公式求值引擎核心算法(已有
rules→ 表达式路径够用)。
2. 产品约定(已确认)
| 项 | 结论 |
|---|---|
| 字段入池方式 | 表单控件属性勾选「参与流程条件分支」(方案 A) |
| 必填联动 | 勾选 ⇒ 强制 required=true,必填开关禁用;取消勾选后才能改回选填 |
| 可勾选控件 | 仅:数字、金额、单选、下拉、日期 |
| 条件 UI | 纯可视化;无高级公式 |
| 多条件 | 同一分支内多条规则 AND |
| 默认分支 | isDefault=true,不配 rules |
| 取消勾选有引用 | 拦截,提示先到流程设计删除对该字段的条件引用 |
| 架构方案 | 方案 1:Schema 打标 + conditionGroups[].rules |
3. 架构
[2 表单设计] [3 流程设计]
FormCreate 字段属性 FlowDesigner 条件抽屉
· props.useInCondition · 下拉 = 已勾选字段(展示 title)
· 勾选 ⇒ required 锁定 · 编辑 rules[{field,op,value}]
↓ ↓
form_schema_json flow_tree_json
↘ ↙
发布校验 / 运行引擎
· 参与字段必须 required
· rules 只引用合法参与字段
· _match_condition_group 优先 rules
职责边界
- 表单: 谁可以进入条件池,并保证运行时有值(必填)。
- 流程: 如何用这些字段做比较。
- 引擎: 基本沿用现有
rules匹配;新配置不再依赖用户手写when。
4. 数据契约
4.1 表单字段(form_schema_json)
在合格控件的 props(或项目统一挂载的扩展字段,与 FormCreate 属性面板约定一致)增加:
| 属性 | 类型 | 说明 |
|---|---|---|
useInCondition |
boolean |
是否参与流程条件分支 |
required |
boolean |
useInCondition === true 时必须为 true |
可勾选 type(实现时映射现有 FormCreate type 名):
- 输入框:如
input(运算符仅==/!=) - 数字:如
inputNumber - 金额:如项目内金额控件 type(若与数字共用则同一逻辑)
- 单选:如
radio - 下拉:如
select - 日期:如
datePicker/date
附件、说明、布局、公式展示等控件不展示该开关。开关位于右侧「组件配置」Tab 的基础字段区(baseRule),非浮层。
4.2 条件分支组(flow_tree_json)
interface ConditionGroup {
name: string
isDefault?: boolean
/** 新配置主存;默认分支为空数组 */
rules: Array<{
field: string
op: '>' | '>=' | '<' | '<=' | '==' | '!='
value: string | number
}>
/** 存量兼容:仅运行时读取;新保存应清空 */
when?: string
child: FlowNode | null
}
运算符策略
| 字段类型 | 可用 op |
|---|---|
| 数字 / 金额 / 日期 / 输入框 | > >= < <= == != |
| 单选 / 下拉 | == != |
同组多条 rules:引擎现有逻辑拼为 AND(与 oa_engine._match_condition_group 一致)。
4.3 引擎行为(保持兼容)
_match_condition_group 已支持:
isDefault或空规则 → 记为默认分支候选when字符串公式rules列表 → 生成临时公式再eval_formula
本需求约定: 设计器新写入以 rules 为准;保存可视化配置后清空同组 when,避免双源不一致。存量仅有 when 的实例版本仍可运行。
5. 交互
5.1 表单设计
- 选中合格控件:属性面板显示「参与流程条件分支」。
- 打开开关:设置
useInCondition=true、required=true,禁用必填控件。 - 关闭开关:若任意条件节点
rules[].field仍引用当前field→ 拦截并提示去流程设计处理;无引用则允许关闭并恢复必填开关可编辑(关闭后不强制把required改回false,仅解锁)。 - 可选:画布角标「用于分支」(Demo 已示意,实现按需)。
5.2 流程设计
- 条件节点抽屉:去掉「条件公式」输入框。
- 规则行:字段下拉(label=标题,value=
field)+ 运算符 + 值;单选/下拉值用选项列表。 - 空池:提示先到步骤 2 勾选;禁用添加规则。
- 默认分支:禁用规则编辑,
rules=[]。 - 非默认:至少一行完整规则;支持「+ 且条件」。
- 树上分支标签:人话预览(如「请假天数 大于 3」),不展示
{field}。
5.3 设计器数据流
designer/index.vue将当前formSchema(或从中解析的条件候选字段列表)传入FlowDesigner。- 候选列表过滤:
useInCondition === true且 type 在白名单。
6. 校验
6.1 前端(保存草稿 / 切步)
- 建议:切换到流程步或保存草稿时做软提示;发布做硬拦截。
6.2 发布(oa_publish + 前端发布前)
| 检查 | 处理 |
|---|---|
useInCondition 但 required 不为真 |
发布前自动纠正为 required,或拦截(推荐自动纠正并写入 schema) |
非默认分支 rules 为空或 field/op/value 缺失 |
拦截:「请完善条件分支」 |
rules.field 在 schema 中不存在或未 useInCondition |
拦截:「条件引用了无效字段」 |
分支仅有存量 when、无有效 rules |
不允许发布;提示用可视化重新配置 |
| 默认分支缺失或不唯一 | 沿用现有发布规则 |
6.3 运行时
- 发起校验:必填字段由动态表单 required 保障。
- 分支匹配:
form_data[field]+rules;不另建变量表。
7. 存量与迁移
| 场景 | 行为 |
|---|---|
已发布版本仅含 when |
运行时继续按公式走;不影响在途实例 |
| 打开草稿/新版本编辑 | 条件抽屉:若无 rules 仅有 when,展示提示「请用可视化重新配置」;保存后写入 rules 并清空 when |
| V1 不做自动公式→rules 解析 | 避免半吊子解析;配置者重配一次即可 |
8. 改动面(实现指引)
| 层 | 内容 |
|---|---|
| 前端表单 | FormCreate 属性面板扩展 useInCondition + 必填锁定 |
| 前端流程 | FlowDesigner.vue 条件 UI;types.ts 明确 rules 形状 |
| 前端设计器壳 | designer/index.vue 传递 form 候选字段给流程步 |
| 后端 | oa_publish 校验补强;引擎优先不改或仅单测覆盖 rules 路径 |
| 文档/Demo | 本 spec + 已有 mockup |
9. 验收标准
- 配置者无需知道
field变量名即可配置「天数大于 3」类分支。 - 未勾选参与的字段不会出现在条件字段下拉中。
- 勾选参与后发起页该字段必填且属性上无法关掉必填。
- 发布应用后:满足条件走对应分支,否则走默认分支。
- UI 上不再出现条件公式输入框。
- 试图取消仍被引用的「参与分支」勾选时被拦截并有中文提示。
10. 测试要点
- 单元:
rules匹配(数字比较、字符串等于、默认分支回落)— 扩展现有test_oa_engine/test_oa_publish。 - 发布:引用未勾选字段应失败;仅有
when无rules应失败。 - 前端手测:勾选锁定必填、取消有引用拦截、下拉只含勾选字段、人话标签、端到端请假式流程。