日期: 2026-07-22
状态: 已批准(实现计划见 docs/superpowers/plans/2026-07-22-oa-related-approval.md)
方案: 方案 1 — form_data 仅存 instanceId[],展示时 enrichment 实时拼装概要;提交写 oa_relation
界面模式: 对齐钉钉「关联审批单」;视觉遵循 Fresh Mint(docs/web-admin-ui-spec-fresh-mint.md)
前置文档: docs/superpowers/specs/2026-07-14-oa-approval-dingtalk-design.md §4.5 / §5.5
决策记录:
completed(已通过);支持多选oa-fc-host 对称注册、无该控件的旧应用行为不变在 OA 审批「2 表单设计」中提供可拖拽的「关联审批单」控件;发起时可选择本人已通过的历史申请,在当前单中展示概要(可展开看全字段),并支持跳转历史单详情。
| 能力 | 说明 |
|---|---|
| 设计器控件 | 左侧可拖;type=relatedApproval;右侧基础属性(标题、必填、提示) |
| 发起选单 | 弹窗;本人 + 已通过 + 任意应用;关键词/分页;多选;已选项禁用 |
| 概要展示 | 收起/展开;Web 标签流横排;移动逐行 |
| 持久化 | form_data[field]=string[];提交写 oa_relation(含 field_key) |
| 详情回显 | 只读同一控件;可展开/跳转 |
| 权限 | 选单与 enrichment 服务端校验;防越权点选 |
参考 FcDesigner 添加新组件,必须补齐四层:
| 层 | 要求 |
|---|---|
| Runtime 组件 | Vue 组件(如 OaRelatedApproval.vue):选单、列表、展开收起、v-model 为 string[] |
| form-create 注册 | formCreate.component('relatedApproval', Comp)(必要时双写大小写/别名,但对外 type 固定 relatedApproval) |
| DragRule | menu: 'main'(基础组件);name/label/icon/input/rule()/props();validate 对齐数组/必填 |
| 设计器注册 | FcDesigner.component(...) + designer.addComponent(dragRule) 或全局 FcDesigner.addDragRule |
对称注册(SHALL):
web-admin/src/main.ts(发起/详情运行时)web-admin/src/oa-fc-host/main.ts(设计器 iframe)禁止:
upload/input 冒充关联控件(与本仓附件补丁路径不同)rule.type 与后端 oa_publish.ALLOWED_CONTROL_TYPES 不一致(现已含 relatedApproval)UI 样式(SHALL):
dialog-form-layout / 列表习惯,遮罩无 backdrop blur{
"type": "relatedApproval",
"field": "<uniqueId>",
"title": "关联审批单",
"info": "",
"$required": false,
"props": {}
}
V1 props 可不扩展业务过滤项;后续若开放设计器过滤,再增显式字段,保持向后兼容。
| 控件 | JSON 形态 |
|---|---|
| 关联审批单 | string[](instanceId 列表;去重;顺序=用户选择顺序) |
符合 OA 双端契约(§4.6):禁止 DOM / 组件实例 / 本地 File 进入 form_data。
沿用现表:
| 字段 | 含义 |
|---|---|
from_instance_id |
当前新实例 |
to_instance_id |
被关联历史实例 |
field_key |
表单字段 field(多控件时区分) |
tenant_no 等 |
公共字段规范 |
提交时:扫描当前版本 schema 中所有 relatedApproval 字段 → 取其 form_data 数组 → 写关系行。
顶层请求体 relatedInstanceIds 保留作兜底(无 field_key);主路径以 form_data 为准。
前缀遵循现有 /api/admin/... OA 路由;租户取当前用户,不信任客户端覆盖。
initiator_user_id = 当前用户、status = completed、tenant_no、del_flag=0id, appName, title?, applyTime, status(列表可先不带全字段,点选后再 enrichment)ids: string[]completedunavailable: true),不导致整接口 403{
id: string
appName: string
applyTime: string
status: string
fields: Array<{ label: string; value: string; fullWidth?: boolean }>
}
在现有 start_instance 中:
to_instance_id 列表(去重)oa_relation(带 field_key)relatedInstanceIds(无 field_key)V1 不改详情主接口形状:前端根据 form_data / relatedInstanceIds 再调 enrichment。
二期若有性能问题,再给 get_instance_detail 附加 relatedSummaries。
对历史实例的 form_schema + form_data:
| 对方控件类型 | 概要展示 |
|---|---|
| 常规输入/选择/日期/金额等 | label + 格式化后的文本值 |
| 附件 / 图片 / 上传 | N 个(不内嵌文件列表) |
嵌套 relatedApproval |
屏幕:已关联 M 条(可跳转,不嵌套缩略卡);打印:多行递归展开业务字段,最多 3 层。细则见 2026-07-22-oa-related-approval-nested-print-design.md |
| 布局 / 说明 / 纯展示 | 跳过 |
| 长文本 | 可标 fullWidth;展开时单独占行 |
fields 的前 3 条fieldsdisplay:flex; flex-wrap 标签流,尽量一行多字段label:value)点击应用名(或行标题)→ 打开只读详情弹窗(盖在当前发起/详情等界面之上,不关父弹窗);权限不足时提示,不白屏。细则见 2026-08-11-oa-related-approval-detail-dialog-design.md。
| 模块 | 职责 |
|---|---|
OaRelatedApproval.vue |
运行时控件(选单、列表、展开收起) |
oa-related-approval-rule.ts |
DragRule |
setupOaRelatedApproval(...) |
双侧注册入口(对称 setupFormCreateUpload) |
api/oaApproval.ts |
选单 + enrichment 客户端 |
| 发起页 / 详情页 | 无需特殊分支(form-create 按 type 渲染);确保注册已执行 |
设计器预览:只读空态或示意条即可,SHALL NOT 因未登录选单 API 而报错崩溃。
| 场景 | 行为 |
|---|---|
| 选单无数据 | 空态文案 |
| 篡改不可关联 ID | enrichment/提交失败,明确错误,不写关系 |
| 历史单删除或对当前用户不可见 | 占位「无法查看」;不阻断当前单保存(已提交关系保留) |
| 必填未选 | FormCreate 校验拦截 |
| 重复 ID | 选单禁用;提交去重 |
| 字段极多 | 展开区域可滚动 |
| 无该控件旧应用 | 行为不变 |
type 为 relatedApproval,发布校验通过completed 实例;可多选、可删oa_relation 正确且含 field_key;详情可回显并跳转oa_relation(field_key)相对 2026-07-14 总设 §5.5「选择有权查看的实例」:本需求收窄为 本人发起 + 已通过;展示从「可跳转」增强为 可展开的全字段概要。若与总设冲突,以本文为关联审批单专项权威,总设可在归档时回写一句交叉引用。
2026-07-22 嵌套/打印修订:屏幕嵌套与打印递归行为以 2026-07-22-oa-related-approval-nested-print-design.md 为准(本文 §5 嵌套行已改为交叉引用)。