现象(真机 UI 复测,os-tianshun-ehr QIF 审批)
同一条待审批请求,两个入口看到的审批 UI 完全不同:
- 业务记录页(QIF 记录详情,当前审批人登录):页头只有「批准」「驳回」两个按钮;More actions 里全是记录操作(升级为NCR/编辑/分享/删除)。转派 / 退回 / 要补充材料零入口,决策也不支持附件。
- 审批列表入口(
sys_approval_request 的列表/详情):有完整动作集 —— Approve / Reject / Reassign / Send back / Request info(+ 提交人的 Remind / Recall / Resubmit),批准/驳回带附件参数。
- 两边文案也不一致:comment 字段 label、驳回确认语等各是一套。
根因:同一件事两套互不相干的实现
服务端能力是全的,九个动作都有 REST 路由(framework packages/rest/src/rest-route-ledger.ts:188-199):approve / reject / recall / revise / resubmit / reassign / remind / request-info / comment。
console 里却有两条独立 UI 路径:
- 声明动作路径(全功能):
sys_approval_request 把 8 个决策/继续动作声明为对象元数据 action(framework packages/plugins/plugin-approvals/src/sys-approval-request.object.ts:250-405,objectui#2678 P2-4),console 通用 action runtime 渲染。可见性走服务端算好的 record.viewer.can_act / is_submitter / can_override(#3310 / #3424),批准/驳回带决策附件(#3266)。
- 记录页硬编码路径(残缺):
RecordDetailView.tsx 里手写注入 approve/reject 两个按钮(packages/app-shell/src/views/RecordDetailView.tsx:1687-1715),走 useRecordApprovals hook,该 hook 只实现了 approve / reject 两个动作(packages/app-shell/src/hooks/useRecordApprovals.ts:74-75),没有 reassign/revise/request-info,没有附件,文案独立维护。
附带的功能性缺陷:群组审批人在记录页看不到任何决策按钮
记录页的 canDecide 是客户端判断:
// useRecordApprovals.ts:161
const canDecide = !!pendingRequest && !!currentUserId
&& (pendingRequest.pending_approvers ?? []).includes(currentUserId);
而 position/team/department 等群组审批人在 pending_approvers 里存的是 position:xxx 之类的 type:value 字面量(framework approval-service 注释明确此为 human-readable CSV),客户端 includes 永远判不中 → 这类审批人在业务记录页连批准/驳回都不显示,只能绕道审批列表。声明动作路径走服务端 viewer.can_act(与服务端授权同一套判定),无此问题。
建议修复方向
业务记录页废弃硬编码的两键注入,改为:
- 拉取该记录 pending 的
sys_approval_request(带服务端 viewer 块);
- 复用
sys_approval_request 上的同一套服务端声明动作渲染到记录页头(约定映射:record_section/list_item → 宿主记录页的 header/overflow 位置);
useRecordApprovals 的 decide/canDecide 逻辑退役(仅保留状态徽章与 lock_record 读取)。
这样五动作入口、附件参数、文案、权限门控一次对齐,后续新增决策动作只改元数据即可,无需再动 console。
参考
- 现场复测记录:QIF
QIF202607310002 提交审批(01 审批中,节点=质检部部长),审批人 qcdir@tianshun.test
- 相关:objectui#2678(P2-4 声明动作)、framework#3310(viewer 块)、framework#3424(can_override)、framework#3266(决策附件)
现象(真机 UI 复测,os-tianshun-ehr QIF 审批)
同一条待审批请求,两个入口看到的审批 UI 完全不同:
sys_approval_request的列表/详情):有完整动作集 —— Approve / Reject / Reassign / Send back / Request info(+ 提交人的 Remind / Recall / Resubmit),批准/驳回带附件参数。根因:同一件事两套互不相干的实现
服务端能力是全的,九个动作都有 REST 路由(framework
packages/rest/src/rest-route-ledger.ts:188-199):approve / reject / recall / revise / resubmit / reassign / remind / request-info / comment。console 里却有两条独立 UI 路径:
sys_approval_request把 8 个决策/继续动作声明为对象元数据 action(frameworkpackages/plugins/plugin-approvals/src/sys-approval-request.object.ts:250-405,objectui#2678 P2-4),console 通用 action runtime 渲染。可见性走服务端算好的record.viewer.can_act / is_submitter / can_override(#3310 / #3424),批准/驳回带决策附件(#3266)。RecordDetailView.tsx里手写注入 approve/reject 两个按钮(packages/app-shell/src/views/RecordDetailView.tsx:1687-1715),走useRecordApprovalshook,该 hook 只实现了approve/reject两个动作(packages/app-shell/src/hooks/useRecordApprovals.ts:74-75),没有 reassign/revise/request-info,没有附件,文案独立维护。附带的功能性缺陷:群组审批人在记录页看不到任何决策按钮
记录页的
canDecide是客户端判断:而 position/team/department 等群组审批人在
pending_approvers里存的是position:xxx之类的 type:value 字面量(framework approval-service 注释明确此为 human-readable CSV),客户端 includes 永远判不中 → 这类审批人在业务记录页连批准/驳回都不显示,只能绕道审批列表。声明动作路径走服务端viewer.can_act(与服务端授权同一套判定),无此问题。建议修复方向
业务记录页废弃硬编码的两键注入,改为:
sys_approval_request(带服务端viewer块);sys_approval_request上的同一套服务端声明动作渲染到记录页头(约定映射:record_section/list_item→ 宿主记录页的 header/overflow 位置);useRecordApprovals的 decide/canDecide 逻辑退役(仅保留状态徽章与lock_record读取)。这样五动作入口、附件参数、文案、权限门控一次对齐,后续新增决策动作只改元数据即可,无需再动 console。
参考
QIF202607310002提交审批(01 审批中,节点=质检部部长),审批人qcdir@tianshun.test