Docs / 菜单管理

菜单管理

GoPress 内置完整的导航菜单管理模块,支持多菜单位置、多级嵌套,并预留了插件扩展钩子。

核心架构

core/menu/
├── Menu          # 菜单实体(ID/Name/Location)
├── Item          # 菜单项(Title/URL/Target/ContentID/Children 树形嵌套)
├── Store         # 内存缓存 + DB 持久化(按 location 和 ID 双索引)
└── Hooks         # menu.location.resolve / menu.deleted 通用扩展点

功能特性

功能 说明
位置注册 主题通过 app.MenuStore().RegisterLocation("header", "顶部导航") 声明可用位置
树形结构 菜单项支持任意层级嵌套(ParentID → Children),自动构建树
内存缓存 LoadAll() 启动时加载全部菜单到内存,GetByLocation() 零 DB 查询
内容关联 菜单项可关联 ContentID,URL 自动解析为对应内容的永久链接
后台管理 创建/编辑/删除菜单,拖拽排序菜单项,分配显示位置
插件扩展 menu.location.resolve 允许插件替换某位置最终菜单,menu.deleted 允许插件清理关联数据

主题中使用菜单

主题在 Setup() 中注册需要的菜单位置:

func (t *MyTheme) Setup(app coreTheme.App) {
    app.MenuStore().RegisterLocation("header", "顶部导航")
    app.MenuStore().RegisterLocation("footer", "底部导航")
}

模板中渲染:

{{$menu := menuByLocation "header"}}
{{if $menu}}
    <ul class="nav-menu">
        {{range $menu.Items}}
            <li><a href="{{.URL}}" class="{{if isMenuURLActive $.Ctx .URL}}active{{end}}">{{.Title}}</a></li>
        {{end}}
        {{renderHook "header.nav.after" .}}
    </ul>
{{end}}

当前菜单高亮应基于当前请求 URL 与菜单项 URL 判断,不要在可复用主题里写死内容类型名、菜单标题或 .ActivePage 标识。

多语言菜单

多语言插件注册 menu.location.resolve filter + menu.deleted action,实现透明的语言菜单切换,主题和模板代码零修改

下面以主题声明的 product 内容类型 URL 为例,实际路径由当前内容类型的 rewrite_slug 决定。

请求 /zh/products
  → 中间件设置 goroutine 级语言: menu.SetRequestLang("zh")
  → 模板调用 menuByLocation "header"
    → Store.GetByLocation("header") → 取到 header 位置的菜单
    → menu.location.resolve filter 触发:
        1. 查翻译表确定当前菜单的实际语言
        2. 通过 trid 找到 zh 语言对应的菜单
        3. 从 menusById 缓存取出翻译菜单
        4. 克隆 + URL 重写(本地链接加 /zh 前缀,内容关联项解析翻译版 slug)
    → 返回中文菜单(含重写后的 URL)

菜单项如果关联的是内容记录,应优先保存 ContentID,由 core 按当前 Rewrite 注册表解析 URL。这样后续把某个内容类型的 rewrite_slugproducts 改成 catalog 时,菜单不需要逐条手动改链接。

后台「翻译管理 → 菜单翻译」按主题注册的菜单位置展示,每个位置每种语言一个下拉框,一键保存分配:

📍 header (顶部导航)
  🇬🇧 English:  [main-header ▾]
  🇨🇳 中文:      [main-header-zh ▾]

📍 footer (底部导航)
  🇬🇧 English:  [-- 未分配 -- ▾]
  🇨🇳 中文:      [-- 未分配 -- ▾]

[保存菜单分配]

详见 多语言插件