日期: 2026-07-30
范围: web-admin 审批设计器步骤 2(表单设计)+ 步骤 3(条件分支)+ 发起/详情/打印运行时;backend 发布白名单、发起校验、条件匹配
关联: docs/superpowers/specs/2026-07-27-oa-dept-select-design.md;docs/superpowers/specs/2026-07-15-oa-condition-from-form-design.md;docs/superpowers/specs/2026-07-30-oa-money-field-design.md
状态: 已实现
OA 审批「2 表单设计」需提供可拖拽的 人员 控件:从本租户系统用户表选择一人或多名人员;展示与交互对齐已落地的 部门 控件。勾选「参与流程条件分支」后,可在「3 流程设计」中配置钉钉式「包含」条件(右侧可选多人,任一命中即通过)。
| 项 | 结论 |
|---|---|
| 展示/交互 | 对齐「部门」:PC 下拉 + 窄屏抽屉;多选 tag 在选择框内 |
| 选择能力 | 默认可多选;设计器可改为单选;可配 max |
| 数据源 | sys_user(fetchUserList,status=1 启用用户);租户隔离走现有 admin API |
| 存值 | 单选 { id, name };多选同结构数组(name 为展示名快照) |
| 条件运算符 | 仅「包含」(contains);不提供等于/不等于 |
| 包含语义 | 条件右侧可多选人;表单人员 id 集合 ∩ 条件 id 集合 非空 即命中(OR) |
| 实现路径 | 自定义 FormCreate type=person(四层扩展,同部门/金额) |
assigneeType 策略)form_data 须可映射)对齐 FormCreate / FcDesigner 四层扩展:
| 层 | 内容 |
|---|---|
| Runtime | OaPersonSelect.vue:v-model 为对象或对象数组 |
| FormCreate 组件注册 | formCreate.component('person', …) |
| DragRule | menu: 'main';label: '人员';props.multiple 默认 true |
| 双侧注册 | 主应用 + oa-fc-host 均调用 setupOaPersonSelect |
[设计器 DragRule] → form_schema_json.type = "person"
↓
[OaPersonSelect] ← fetchUserList(status=1)
↓
form_data[field] = { id, name } | { id, name }[]
↓
[条件] useInCondition → op=contains, value=string[] (user ids)
↓
[引擎] id 集合交集非空 → 命中分支
[详情/打印] 优先展示 name 快照
{
"type": "person",
"field": "Fxxxx",
"title": "协同人",
"info": "",
"$required": false,
"useInCondition": false,
"props": {
"multiple": true,
"max": null,
"useInCondition": false
}
}
| 属性 | 说明 |
|---|---|
| 标题 / 提示信息 / 必填 | 与现有控件一致 |
| 允许多选 | Switch,默认 true |
| 最大可选数 | 可选;仅多选时生效;不填不限制 |
| 参与流程条件分支 | 基础配置全局开关(person 加入 CONDITION_ELIGIBLE_TYPES 后可见);勾选后强制必填 |
form_data 契约(锁定)type OaPersonValueItem = {
id: string // sys_user.id (UUID)
name: string // 提交时展示名快照:优先 nickName,空则 userNo
}
// 单选(props.multiple === false)
type PersonFormValueSingle = OaPersonValueItem | null
// 多选(props.multiple === true,默认)
type PersonFormValueMulti = OaPersonValueItem[]
约束:
id、name 均为非空字符串。multiple 不一致的标量/对象混用。name 快照。el-select:filterable、clearable;multiple 时多选,已选以 select 内 tag 展示(对齐部门 tree-select 多选表现)。nickName(空则 userNo);可附带次要信息区分重名,写入 name 的仍为主展示名。el-drawer(仿部门)。name;空为 —。max 有值且超限:前端 ElMessage.warning,不写入;后端校验兜底。fetchUserList({ status: '1', page, pageSize }) 分页拉全量(与发起页 / 流程设计器选人一致)。{ id, name }。FormCreate 在 oa-fc-host 中有两处预览相关能力,人员控件 SHALL 同时可用:
| 场景 | 行为约束 |
|---|---|
| 顶部 PC / Pad / Mobile 设备切换 | Mobile 时画布 ._fc-m-drag.mobile 固定约 400px 宽。iframe 视口仍可能 ≥768,不能仅依赖 matchMedia 才可用。PC 路径的 el-select SHALL 全宽、min-width:0,多选 tag 可折叠/换行,禁止横向撑破画布。 |
| 工具栏 预览 按钮 | 弹窗内 ViewForm 渲染同一套已注册 person 组件;setupOaPersonSelect 必须在 oa-fc-host 注册,否则预览空白。抽屉(若触发)append-to-body。 |
| 发起页 流程预览 | 填写人员后 form_data 进入 fetchOaFlowPreview;条件 contains 由引擎集合匹配驱动分支展示。 |
窄屏抽屉(matchMedia max-width: 767px)仍保留,用于真实窄 viewport / 真机,与部门一致。
全局运行时样式:oa-fc-runtime.scss 将 .oa-person-select 与 .oa-dept-select 并列,保证列宽内不溢出。
CONDITION_ELIGIBLE_TYPES 与后端 oa_publish.CONDITION_ELIGIBLE_TYPES 均加入 person。useInCondition 后出现在条件候选列表;发布前强制 $required / required(现有归一化逻辑)。// ConditionOp 扩展
type ConditionOp = '>' | '>=' | '<' | '<=' | '==' | '!=' | 'contains'
interface ConditionRule {
field: string
op: 'contains' // person 字段仅允许此 op
value: string[] // 用户 id 列表,长度 ≥ 1
}
formIds = extract_user_ids(form_data[field]) // 单对象或数组 → Set<id>
condIds = Set(rule.value)
hit = |formIds ∩ condIds| > 0
类比钉钉审批「发起人属于这些人」:条件侧多人,任一出现在表单已选人员中即命中。
person 字段:运算符固定为「包含」(可只读展示)。value 为 string[]。{标题} 包含 张三、李四。contains 且 value 为空 → 拒绝。{field} == 'x' 公式字符串做比较。_match_condition_group(或等价路径)对 op === 'contains' 走专用集合判断;从 form 值中抽取 id(兼容单对象与数组)。== / 数值比较逻辑保持不变。| 路径 | 职责 |
|---|---|
web-admin/src/components/oa-approval/OaPersonSelect.vue |
运行时控件 |
web-admin/src/utils/oa-person-value.ts |
normalize / 展示 |
web-admin/src/utils/oa-person-select-rule.ts |
DragRule |
web-admin/src/utils/oa-form-create-person.ts |
注册入口 |
| 路径 | 职责 |
|---|---|
web-admin/src/main.ts、oa-fc-host/main.ts |
setupOaPersonSelect |
oa-condition-fields.ts |
合格类型 + contains + opsForFieldType |
flow-tree/types.ts |
ConditionOp / ConditionRule.value |
ConditionRuleEditor.vue |
person 右侧多选 |
utils/oa-approval-print.ts 等 |
person 打印展示 |
| 路径 | 职责 |
|---|---|
app/services/oa_publish.py |
FILLABLE_TYPES / CONDITION_ELIGIBLE_TYPES 加入 person |
app/services/oa_person_select.py(新建) |
form_data 值形态校验(仿 oa_dept_select) |
app/services/oa_engine.py |
contains 集合匹配 |
app/services/oa_related_approval.py |
摘要格式化(仿 dept) |
| 发起/提交入口 | 挂接 person 校验 |
| 场景 | 行为 |
|---|---|
| 用户列表加载失败 | 选项空;可提示;不阻断设计器 |
超 max |
前端拦截 + 后端校验 |
条件 contains 且 value 空 |
发布/保存流程拒绝 |
| 值形态非法 | 发起返回中文错误列表 |
useInCondition 对 person 可见;勾选后必填。[A,B] → 命中;条件仅 [B] 且表单无 B → 不命中。person 的应用不报未知控件。FILLABLE/CONDITION 白名单 + person 校验骨架OaPersonSelect + DragRule + 双侧注册contains + ConditionRuleEditor 人员多选{ id, name } / 数组;流程预览随 contains 条件切换分支