日期: 2026-07-27
范围: web-admin 审批设计器步骤 2(表单设计)+ 发起/详情运行时;backend 发布白名单已有 dept,补齐值形态校验与打印
状态: 已评审待实现
OA 审批「2 表单设计」需提供可拖拽的 部门 控件,供发起人选择本租户组织树(sys_dept),与钉钉式「部门」及既有规格 docs/superpowers/specs/2026-07-14-oa-approval-dingtalk-design.md §4.5 / §4.6 对齐。
当前发布字典已允许 type: "dept",但设计器与运行时尚未落地自定义控件。
| 项 | 结论 |
|---|---|
| 选择能力 | 默认可多选;设计器属性可改为仅单选 |
| 存值 | 单选 { id, name };多选同结构数组 |
name |
全路径快照(分隔符 /) |
| 可选范围 | 任意层级均可选(非仅末级) |
| 实现路径 | 自定义 type=dept(对齐关联审批四层扩展);PC 用 el-tree-select |
| 移动兼容 | 窄屏禁止仅依赖宽屏下拉;须全屏/半屏选择器;Schema/form_data 双端同一份 |
oa_role 等既有策略)对齐 FormCreate / FcDesigner 四层扩展(与「关联审批单」同路径):
| 层 | 内容 |
|---|---|
| Runtime | OaDeptSelect.vue:v-model 为对象或对象数组 |
| FormCreate 组件注册 | formCreate.component('dept', …) |
| DragRule | menu: 'main';name/label 为部门;props.multiple 默认 true |
| 双侧注册 | 主应用(发起/详情)+ oa-fc-host(设计器 iframe)均调用 setupOaDeptSelect |
数据源:现有 fetchDeptTree()(本租户组织树),不另造 API。
[设计器 DragRule] → form_schema_json.type = "dept"
↓
[OaDeptSelect] ← fetchDeptTree
↓
form_data[field] = { id, name } | { id, name }[]
↓
[后端发起校验] → 详情 / 打印优先展示 name 快照
{
"type": "dept",
"field": "Fxxxx",
"title": "所属部门",
"info": "",
"$required": false,
"props": {
"multiple": true,
"max": null
}
}
| 属性 | 说明 |
|---|---|
| 标题 / 提示信息 / 必填 | 与现有控件一致 |
| 允许多选 | Switch,默认 true;false 时仅单选 |
| 最大可选数 | 可选;仅多选时生效;不填则不限制 |
树下拉节点文案:本级名称;选中后输入框 / 发起页 / 详情 / 打印:全路径(与 tree-path 约定一致)。
form_data 契约(锁定)type DeptValueItem = {
id: string // sys_dept.id
name: string // 提交时全路径快照,如 "中科兴皖 / 研发中心 / 前端组"
}
// 单选(props.multiple === false)
type DeptFormValueSingle = DeptValueItem | null
// 多选(props.multiple === true,默认)
type DeptFormValueMulti = DeptValueItem[]
约束:
id、name 均为非空字符串。multiple 不一致的标量/对象混用。name 快照;不强制按 id 重算路径。id 仍存在于当前组织树(允许已删/历史部门快照可读)。本决定更新钉钉规格 §4.6 值类型表中「部门」一行的歧义:发布锁定为 { id, name } / 数组,不再使用裸 string deptId。
el-tree-select(或等价树选)。multiple 跟随 props.multiple。对齐双端规格:「部门/省市区 → 移动端 全屏或半屏选择器,禁止依赖宽屏下拉才能选完」。
v-model。v-model 形态,仅交互壳不同。详情 / 审批页:仅展示路径文案(单选一个 name;多选多个 name 用中文顿号「、」拼接),不可打开选择器。
dept 不注册「参与流程条件分支」开关;CONDITION_ELIGIBLE_TYPES 不包含 dept。
null;多选空数组 → 拦截提示。max:达到上限不可再选并提示。type === "dept"。null;否则须为 { id, name }。{ id, name };必填则 length >= 1;有 max 则 length <= max。ALLOWED_CONTROL_TYPES 已含 dept,保持即可。name。name 用中文顿号「、」拼接。oa-approval-print(及详情只读渲染)对 type === "dept" 特判。| 区域 | 文件(预期) |
|---|---|
| Runtime | web-admin/src/components/oa-approval/OaDeptSelect.vue |
| DragRule | web-admin/src/utils/oa-dept-select-rule.ts |
| 注册 | web-admin/src/utils/oa-form-create-dept.ts;oa-fc-host/main.ts;主应用 form-create 注册点 |
| 打印 | web-admin/src/utils/oa-approval-print.ts |
| 后端校验 | backend/app/services/oa_publish.py 或发起校验模块中的 form_data 校验 |
| Demo(可选) | docs/mockups/oa-dept-select-demo.html 与实现对齐 |
form_data 形态符合 §4;组织改名后旧实例仍显示快照路径。dept 的应用可发布;未知 type 仍拒绝。form_data 形态校验(单选/多选/必填/max)。无。若二期要做「部门字段参与条件分支」或小程序原生页,另开变更,不修改本节契约。