运行控制台导航与页面挂载
运行控制台(/console)的左侧导航不由路由配置或函数目录决定,只有一个来源:菜单管理中维护的菜单树 + 显式挂载到菜单的已发布页面。想让一个页面出现在运行控制台,必须同时满足三件事:
菜单节点存在(菜单管理创建) + 页面已发布 + 页面挂载到该菜单三者缺一不可——发布本身不会让页面进控制台。详细架构规则见 运行控制台动态菜单。
完整工作流
第 1 步:在菜单管理中创建菜单
入口:侧边栏 函数与页面 → 菜单管理(/functions/menus)。
默认菜单骨架:全新
(gameId, env)scope 首次访问菜单(菜单管理页或运行控制台)时,系统会自动导入一组常用游戏后台菜单组(玩家管理 / 运营 / 支付订单 / 公告 / 审计,定义在部署目录configs/default-menus.json)。种子只在 scope 无任何菜单时导入一次,永不覆盖用户数据;不需要可删除该文件(缺失即禁用),也可删掉种子菜单后自行重建。
点击 新建菜单,填写:
| 字段 | 说明 |
|---|---|
菜单标识(menuKey) | 字母开头,仅字母/数字/中划线/下划线,长度 1–64。它就是控制台路由段:页面挂到 player 菜单后路径为 /console/player/<pageKey> |
菜单名称(labels) | 多语言标题(zh-CN / en-US),控制台侧边栏显示用 |
| 图标 | 可选,侧边栏菜单图标 |
权限(permission) | 可选。填写后仅持有该权限的用户可见此菜单(含整棵子树) |
| 是否可见 | 关闭后此菜单(含子树)不进控制台导航 |
| 排序 | 组内顺序;也可在树中拖拽调整 |
菜单支持任意层级嵌套:树上每个节点有 加子菜单 按钮。删除菜单会级联删除其全部子菜单,并自动解除挂在下面的页面挂载(页面本身与发布状态不受影响)。
第 2 步:发布页面
页面必须存在 active 发布快照 才会上控制台。draft-only 页面(编辑器里保存过但未发布)不会出现。
发布路径任选其一:
- 提案收件箱:对生成的 proposal 执行
accept-and-publish(发布确认弹窗内可同时选择挂载菜单,见第 3 步); - Page Studio / 版本管理:对已有草稿执行发布。
第 3 步:把页面挂载到菜单
管理界面入口(推荐,要求 pages:edit 或 admin:all 权限),按场景任选:
场景 A:发布默认页面时一步挂载(提案收件箱)
- 进入 函数与页面 → 页面工作台(
/functions/pages)顶部提案收件箱的 可直接发布 队列; - 点击目标提案行的 发布 按钮;
- 确认弹窗内的 挂载到菜单 下拉中选择目标菜单(可选;不选则仅发布,页面暂不上控制台导航);
- 点击 确定——发布与挂载一次完成,控制台导航即时生效。
场景 B:给已发布/草稿页面改挂载(页面工作台)
- 进入 函数与页面 → 页面工作台(
/functions/pages),底部 高级页面管理 面板默认展开,找到目标页面所在行; - 点击行内 挂载菜单 图标按钮(铅笔/预览旁的层级图标);
- 弹窗内的菜单树中选择目标菜单(树结构与菜单管理一致,支持任意层级子菜单),点击 确定。未挂载页面打开时默认选中第一个菜单——直接确定即完成挂载;清空选择后确定则解除挂载。
已物化页面的提案行也可经 更多(⋯)→ 挂载菜单 直达场景 B(自动定位并打开挂载弹窗)。
场景 C:页面编辑弹窗内联挂载(保存/发布同屏)
页面工作台行内 编辑 打开「页面编辑」弹窗后,左侧「页面信息」卡片内提供 挂载菜单 选择器:
- 打开时回显当前挂载;未改动则不随保存提交(不会每次保存都调挂载 API)。未挂载页面默认选中第一个菜单且视为已改动——保存即随提交挂载(避免显示默认值却不生效的误导);
- 「仅保存草稿」/「保存并发布」均可携带挂载,一次点击完成(挂载失败不回滚保存/发布,提示可稍后重挂);
- 清空选择 = 解除挂载(保存后生效);未挂载页面清空默认值同样表示不挂载。
历史注记:该选择器 2026-09 前放在弹窗 footer,被满屏高度的编辑 body 挤出视口而实际不可见;已移入 body,同时移除了旧「分类 key」输入框(category 仅作为协议字段随存量数据透传,不再提供编辑入口)。
弹窗行为细节:
- 输入框回显当前挂载的菜单,清空后确定即解除挂载(页面从控制台消失,但发布状态保留、直达 URL 仍可访问);
- 页面尚处于 draft 状态时弹窗会提示「挂载关系会保存,但发布后才会出现在运行控制台导航」——draft 页可以先挂载,发布后自动上控制台;
- 保存成功后控制台导航即时生效,无需刷新发布或重新部署。
同一操作也可经 API 完成(适用于脚本/批量场景):
TOKEN=<登录 token>
curl -X PUT "https://<server>/api/v1/pages/<pageKey>/menu" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Game-ID: <gameId>" -H "X-Env: <env>" \
-H "Content-Type: application/json" \
-d '{"menuId": <菜单 id>}'menuId是第 1 步创建菜单返回的数字 id(也可从GET /api/v1/menus列表查到);- 菜单必须与页面同属一个
(gameId, env)scope,跨 scope 挂载返回「菜单不存在」; - 改挂载即时生效,不需要重新发布页面。
解除挂载的 API 形式(与 UI 清空确定等价):
curl -X PUT "https://<server>/api/v1/pages/<pageKey>/menu" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Game-ID: <gameId>" -H "X-Env: <env>" \
-H "Content-Type: application/json" \
-d '{"menuId": null}'第 4 步:在运行控制台查看
刷新运行控制台即可看到:菜单组节点(含嵌套子菜单)+ 组内挂载的页面,二者按 排序值 → 标题 → key 混排。页面条目标题取自该页面最新发布快照的 title。
侧边栏中「运行控制台」子树与控制台页内导航由同一份菜单数据渲染,权限过滤规则一致(菜单 permission、可见性、父级不可达剪枝)。
行为速查
| 场景 | 控制台表现 |
|---|---|
| 页面已发布、已挂载 | 出现在挂载菜单下 |
| 页面已发布、未挂载 | 不出现;直达 /console/<任意段>/<pageKey> 仍可渲染(不会被重定向走) |
| 页面挂载了、未发布(draft-only) | 不出现 |
| 空菜单(无任何挂载页面) | 菜单组节点保留,渲染为指向 /console/<menuKey> 的单个链接(无子菜单可展开);挂载页面后恢复为菜单组 |
菜单带 permission、用户无该权限 | 整棵子树(含挂载页面)不可见 |
菜单不可见(isVisible=false) | 整棵子树不进导航 |
| URL 菜单段与实际挂载不符 | 自动重定向到挂载菜单对应的规范路径 |
| 删除挂载菜单 | 子树级联删除,页面挂载自动解除,页面与发布状态不受影响 |
权限要求
| 操作 | 所需权限 |
|---|---|
| 创建/编辑/删除菜单 | menu:create 或 admin:all |
| 挂载/解除挂载 | pages:edit 或 admin:all |
| 查看控制台菜单 | console:read(菜单树按当前用户权限过滤) |
常见问题
Q:页面发布成功了,为什么运行控制台里没有? 发布不自动进菜单。检查是否执行了第 3 步的挂载,以及菜单是否可见、当前用户是否持有菜单 permission。
Q:挂载错了菜单怎么改? 重新打开行内 挂载菜单 弹窗选新菜单确定(或再 PUT 一次目标 menuId)即可,即时生效,无需解除再挂。
Q:没挂载的页面用户能访问吗? 能。直达 /console/<任意菜单段>/<pageKey> 会正常渲染(不重定向),只是导航里不出现。控制台首页的「已发布页面」统计同样包含未挂载页面。如需限制访问请配合权限控制。
Q:旧版本里发布后自动出现的菜单去哪了? 该行为已移除:控制台导航自 menu_items 唯一驱动版本起,只认「菜单 + 挂载 + 已发布」三要素组合。
Q:我把菜单全删了,重启后怎么又出现了一套默认菜单? 默认菜单种子按「scope 菜单表为空」判定:删光全部菜单并重启服务后,该 scope 首次访问会重新导入一次骨架。想彻底禁用,删除部署目录 configs/default-menus.json 即可(文件缺失 = 种子关闭)。只删个别种子菜单不会触发补种——只要 scope 里还有任意菜单就不会再导入。
