菜单 API
用途与前置条件
scoped.menus 管理后台菜单配置。后台页面优先使用 configs/items/views/loadApis/actions/responses 逐项创建菜单、页面、接口、按钮和响应字段;配置即代码或插件安装可以继续使用 menus.config.* 批量保存完整 MenuConfigInput。subject.menus 是用户运行时入口,用同一套配置投影当前用户可见视图、按钮状态、页面状态和接口响应字段。
新项目不要直接维护底层 nodes、apiBindings 或 owner 关系;这些是编译后的兼容模型,主要服务历史 v2 清单、迁移工具和批量导入。普通后台管理页应把 menus.configs/items/views/loadApis/actions/responses 当作主 API,把 menus.config.* 当作高级整包入口。
使用前需要完成:
pc.init()已成功。- 已通过
pc.scope(scope, defaults?)获取可信 scope 下的管理上下文;后台请求可在defaults里绑定actorId/requestId。 - 需要运行时投影时,已通过
pc.forSubject({ userId, scope })获取当前用户上下文。
我想做什么
签名
关键参数标记:configId 定位一套菜单配置;changes: NonEmptyMenuManagementChangeArray 是增量变更;config: MenuConfigInput 是批量完整配置。
MenuManagementExecuteOptions 有两种形态:
不要只传半套显式参数:只有 previewToken 没有 expectedRevisions,或只有 expectedRevisions 没有 previewToken,都会返回 INVALID_ARGUMENT。menus.config.save/remove/applyChanges 是旧的完整配置批量入口,仍然必须使用 preview 返回的 expected/previewToken。
对象方法还有对应的 previewUpdate/update/previewRemove/remove,签名与 previewCreate/create 一致,只是多了要更新或删除的 menuId/viewId/resource/actionId。
参数对象
增量管理参数
MenuResponseSetInput.owner 有三种写法:
ownerType: 'api' 会匹配当前配置中声明了这个 API 的 load 或 api action。后台页面能定位到具体页面时,更推荐使用 load 或 action,错误更容易排查。
MenuConfigInput
MenuConfigMenuInput
MenuViewInput
load.resource: ApiResource 必须形如 api:GET:/api/orders。actions[].resource: ApiResource | UiResource 可指向后端接口或前端 UI 能力。response?: ResponseProjectionConfigInput 可写在 load 或 actions 上,详见配置接口与响应字段 API。
方法详解:配置管理
menus.config.preview(config, options?)
- 用途:在保存前校验菜单配置,并预览内部菜单、接口、响应字段和已有角色授权的影响。
- 参数:
config是完整MenuConfigInput;options可带actorId/reason/detailBudget。 - 状态影响:只读,不写入配置。
- 原始返回:
ImpactPreview<MenuConfigPlan>;重点读取executable、conflicts、plan.after、expected和previewToken。
menus.config.save(config, options)
- 用途:提交已预览的菜单配置。
- 参数:
config必须与预览一致;options必须包含expected、previewToken,可选actorId/requestId;idempotencyKey只用于高级覆盖默认幂等策略。 - 状态影响:写入
_menu_configs,同步内部菜单节点、接口契约和响应字段索引,并处理受影响角色来源。 - 原始返回:
MutationResult<MenuConfigSaveResult>;配置快照在data.config,内部写入摘要在data.manifestOperations。
menus.config.get(configId)
- 用途:读取指定配置的最新快照;管理端要展示完整菜单树时,用这个方法。
- 参数:
configId为配置 ID。 - 状态影响:只读。
- 原始返回:
VersionedResult<MenuConfigSnapshot>;完整菜单树在data.menus,包含菜单、子菜单、页面、加载接口、按钮和响应字段配置。data.revision可作为管理端展示的版本信息。
menus.config.list(query?)
- 用途:分页读取当前 scope 下的菜单配置摘要。
- 参数:
query可带configId/first/after。 - 状态影响:只读。
- 原始返回:
PageResult<MenuConfigSummary>;摘要包含menuCount/viewCount/actionCount/responseFieldCount。它用于列出多套配置,不用于列出某套配置下的菜单树节点;完整树请用menus.configs.get(configId)或menus.config.get(configId)。
menus.config.previewRemove(configId, options?)
- 用途:预览删除一套菜单配置会移除哪些配置资产。
- 参数:
configId和可选预览上下文。 - 状态影响:只读,不删除。
- 原始返回:
ImpactPreview<MenuConfigRemovePlan>;重点检查removedAssets。当前配置快照删除不会自动改写角色菜单授权,历史授权可通过角色菜单读取和 stale 修复链路处理。
menus.config.remove(configId, options)
- 用途:执行已预览的配置删除。
- 参数:
configId必须与预览一致;options带expected/previewToken。 - 状态影响:删除配置快照并同步移除内部菜单/API 资产;不会自动撤销角色菜单授权。
- 原始返回:
MutationResult<MenuConfigRemoveResult>。
menus.config.previewChanges(changes, options?)
- 用途:一次预览多套配置的保存或删除。
- 参数:
changes: NonEmptyMenuConfigChangeArray,每项是{ operation: 'save', config }或{ operation: 'remove', configId }。 - 状态影响:只读。
- 原始返回:
ImpactPreview<MenuConfigChangeSetPlan>;用于插件安装、模块升级或批量导入前审查。
menus.config.applyChanges(changes, options)
- 用途:原子提交已预览的批量配置变更。
- 参数:原始
changes加预览返回的expected/previewToken。 - 状态影响:批量保存/删除配置,并同步所有内部菜单与接口资产。
- 原始返回:
MutationResult<MenuConfigChangeSetResult>。
方法详解:用户运行时
subject.menus.getViewTree(options)
- 用途:返回当前用户在指定配置下可见的导航树。
- 参数:
options.configId指定菜单配置。 - 状态影响:只读;按当前用户有效角色和菜单授权投影。
- 原始返回:
SubjectRuntimeResult<readonly ViewTreeNode[]>;按钮不会作为树节点返回。
subject.menus.getActionMap(input)
- 用途:返回某个视图下每个按钮或操作是否可见、是否可用以及原因。
- 参数:
input.configId和input.viewId。 - 状态影响:只读。
- 原始返回:
SubjectRuntimeResult<Record<string, ActionPermissionState>>;对象键是 action ID。
subject.menus.getViewState(input)
- 用途:判断当前用户是否允许进入某个视图。
- 参数:可传
{ configId, viewId },也可传{ path }。 - 状态影响:只读。
- 原始返回:
SubjectRuntimeResult<ViewPermissionState>;allowed表示权限允许,navigationReachable表示导航链路可达。
subject.menus.filterResponse(apiResource, payload)
- 用途:按当前用户的响应字段授权裁剪接口响应。
- 参数:
apiResource是api:METHOD:/path;payload是准备返回给前端的数据。 - 状态影响:只读,但会先检查当前用户是否能
invoke该apiResource。 - 原始返回:
SubjectRuntimeResult<unknown>;裁剪后的响应在data。
响应与副作用
保存配置会产生 mutation envelope、审计 ID、revision、缓存失效结果和内部同步摘要。运行时方法不写入数据库,返回 SubjectRuntimeResult<T>,其中 data 是前端真正使用的数据,detailBudget 是诊断信息。
失败与限制
常见失败包括配置 ID 重复或缺失、资源格式无效、响应字段路径非法、自动提交需要显式预览确认、预览 token 过期、revision 冲突和容量超限。load.resource 必须是 api: 资源;响应字段只能引用配置里声明过的字段。保存配置不会自动给任何角色或用户授权。
增量管理自动模式遇到级联删除、撤权删除或不可自动确认的影响时,会抛出 MENU_MANAGEMENT_PREVIEW_CONFLICT。读取 details.operations/conflicts/warnings 给管理员展示,然后调用对应的 preview*(),确认后带 expected/previewToken 执行。