日期: 2026-08-06
范围: web-admin 审批设计器步骤 2(表单设计)勾选 + 步骤 3(流程设计)条件值;backend 条件匹配、发布白名单、单测
关联:
docs/superpowers/specs/2026-07-15-oa-condition-from-form-design.md(表单驱动条件)docs/superpowers/specs/2026-07-30-oa-person-select-design.md(contains / 人员多选)docs/superpowers/specs/2026-07-30-oa-owner-fields-design.md(曾约定 ownerDept 暂不进条件,本期废止该限制)表单「人员 / 归属人」已可勾选参与条件分支(contains + id 交集)。「部门 / 归属部门」值结构同为 {id, name}(可单可多),但前后端白名单均未纳入,条件编辑器也无部门值选择器。
| 项 | 结论 |
|---|---|
| 控件 | dept、ownerDept 均可勾选「参与流程条件分支」 |
| 匹配语义 | 精确 id;表单填下级部门 ≠ 条件选中上级(不含树包含) |
| 运算符 | 仅「包含」contains |
| 条件值 | string[] 部门 id;多选;与表单部门 id 有交集即命中(OR) |
| 条件值 UI | 树形多选(与表单部门控件同源数据 fetchDeptTree) |
| 必填联动 | 勾选 ⇒ 强制必填并锁定,与现网一致 |
| 实现路径 | 镜像人员路径(方案 1) |
person / ownerPerson |
dept / ownerDept |
|
|---|---|---|
| 入池 | useInCondition + 白名单 |
同左(本期补白名单) |
| op | contains |
contains |
| value | 用户 id[] | 部门 id[] |
| 命中 | extract_*_ids(form) ∩ value ≠ ∅ |
同左 |
| RHS UI | 用户扁平多选 | 部门树多选 |
== / != / 「不包含」[2 表单设计] [3 流程设计]
dept / ownerDept ConditionRuleEditor
· useInCondition 开关可见 · 字段候选含勾选后的部门控件
· 勾选 ⇒ required 锁定 · op 仅「包含」
↓ · RHS:el-tree-select 多选部门 id
form_schema_json rules: { field, op:'contains', value: string[] }
↘ ↙
发布 / 运行引擎
· CONDITION_ELIGIBLE 含 dept、ownerDept
· dept_contains_match(form_val, value)
职责边界
value: string[]。contains 时对部门值走 dept_contains_match(与 person/post 并列)。// 表单填报值(已有)
// 单选:{ id: string, name: string }
// 多选:Array<{ id: string, name: string }>
// ownerDept:始终单选对象
// 条件规则(与人员同形)
{ field: string, op: 'contains', value: string[] } // length >= 1 在发布/完善规则时由现有校验约束
命中:
extract_dept_ids(form_data[field]) ∩ Set(value) ≠ ∅
extract_dept_ids:与 extract_person_ids 同构——支持单对象或对象数组,只取非空 id。
预览文案: 格式化字段名 包含 部门A、部门B(有树 map 用名称,否则 id)。
web-admin/src/components/oa-approval/oa-condition-fields.ts:
CONDITION_ELIGIBLE_TYPES 增加 'dept'、'ownerDept'opsForFieldType:dept / ownerDept 与 person 一样仅返回 containsformatConditionPreview:沿用现有 op 文案「包含」(无需新 op)oa-fc-host/App.vue 已用 CONDITION_ELIGIBLE_TYPES 控制开关显隐,加类型即可,不必改宿主逻辑。
ConditionRuleEditor.vue:
isDeptLikeField:type === 'dept' || type === 'ownerDept'el-tree-select(multiple、filterable、check-strictly、collapse-tags),数据来自 fetchDeptTree,节点展示本级 deptName(与表单部门控件一致;不必在条件下拉里拼全路径)defaultValueForType:部门类返回 []不复用完整 OaDeptSelect 组件(表单控件含窄屏抽屉、emit 对象值);条件侧只存 id[],用轻量 tree-select 即可。
沿用现有「流程仍引用该 field → 禁止取消 useInCondition」。部门字段无特殊伪字段,无需改引用集合逻辑。
oa_dept_select.py新增:
extract_dept_ids(raw) -> Set[str]dept_contains_match(form_value, cond_ids) -> boolperson_contains_match / post_contains_match 对齐)oa_engine._eval_condition_rules 中 op == "contains" 且非 __initiator__ 时:
if not (
person_contains_match(form_val, val)
or post_contains_match(form_val, val)
or dept_contains_match(form_val, val)
):
return False
保持与现网「多 helper OR」一致:错误形态抽取为空集,不会误命中。
oa_publish.CONDITION_ELIGIBLE_TYPES 增加 "dept"、"ownerDept"。
index_condition_fields / validate_condition_rules_against_form 自动吃到新类型;不要求为部门单独加「发起人式」校验块(与人员表单字段同级:依赖流程树「规则须完善」+ 字段在 index 内)。
可选增强(非必须):对 dept/ownerDept/person/ownerPerson/post 统一校验 op == contains 且 value 为非空 string 列表——若本期做,须覆盖人员回归;默认可不做,避免扩大范围。
| 场景 | 期望 |
|---|---|
| 表单多选部门与 value 有交集 | dept_contains_match True |
| 仅下级 id、条件为上级 id | False(精确匹配) |
单对象 ownerDept 命中 |
True |
| 引擎条件组含 dept contains | 正确分流 / 走默认 |
| 发布:勾选 dept 字段可被 rules 引用 | 通过 |
| 回归 person / post / initiator contains | 通过 |
文件:backend/tests/test_oa_dept_select.py(补 extract/contains)、backend/tests/test_oa_engine.py(补一条 dept 条件)。
前端:
oa-condition-fields.ts、ConditionRuleEditor.vue(必要时样式微调)
后端:
oa_dept_select.py、oa_engine.py、oa_publish.py、
tests/test_oa_dept_select.py、tests/test_oa_engine.py
文档(旁注,非阻塞):
2026-07-30-oa-owner-fields-design.md §4.2 一句改为「ownerDept 与 dept 同属部门类(contains)」——可选 follow-up,避免历史规格误导。
extract_dept_ids + dept_contains_match + 单测ConditionRuleEditor 树多选