# 单页管理(cms_page)与导航(cms_navigation)关联对接说明 > 面向后端 / website-admin「单页管理」模块负责人。 > 目标:把"菜单结构"与"单页内容"解耦又关联——导航只管菜单层级,单页管理只管正文,二者用 URL(slug)挂钩。 --- ## 1. 约定结论(已与前端确认) | 项 | 约定 | |---|---| | **内容唯一源** | 新建的单页内容一律建在「单页管理」(`cms_page`),按 `slug` 存取;导航节点不再存放单页正文(`design.content` 仅保留给旧租户兼容)。 | | **规范 URL** | 单页对外地址统一为 `/page/{slug}`,例如 `/page/about-us`。 | | **About / Contact** | `/about`、`/contact` 为独立富组件路由,是这两个页面的**规范地址**;`/page/about`、`/page/contact` 仅作兼容入口,前端已 301 跳到顶层(见 §4)。 | | **导航关联方式** | 后台建菜单关联单页时,把 `nav.path` 写成 `/page/{slug}`(前端已支持,无需额外接口)。`CmsNavigation.pageId` 作为后端对账键保留。 | | **旧数据兼容** | `/page/{数字}`(数字 navigationId)仍走旧 `cms_navigation + design.content`,不破坏旧租户。 | --- ## 2. 前端已具备的能力(后端无需改动即可生效) - `getNavLink(nav)`:当 `nav.model === 'page'` 或 `nav.path` 以 `/page/` 开头时,直接返回该 path,**不会追加 `?navId=`**,单页菜单 URL 干净。 - `app/pages/page/[id].vue`: - 非数字 slug → 调 `/api/page/detail?path={slug}` → 取 `cms_page` 已发布单页正文。 - slug 为 `about` / `contact` → 301 收敛到 `/about`、`/contact`。 - 列表/详情类栏目(article/product/case)维持原 `?navId=` 行为,不受影响。 --- ## 3. 后台需要配合的 3 件事 ### 3.1 单页管理创建页面时生成 slug - `cms_page.slug` 必须**全局唯一、SEO 友好**(建议英文小写 + 连字符,如 `about-us`、`privacy-policy`)。 - 同一站点内 slug 不可重复;应做唯一性校验并报错提示。 - 不建议用中文或含空格的 slug(不利于 URL 与 SEO)。 ### 3.2 导航菜单关联单页时填 path 两种方式任选其一(推荐方式 A,零成本): - **方式 A(推荐)**:在「单页管理」与导航建立关联时,把菜单 `nav.path` 直接写为 `/page/{slug}`。前端拿到即可跳转,无需新增接口。 - **方式 B**:只填 `nav.pageId = cms_page.id`,由后台在返回导航树时**回写** `nav.path = /page/{slug}`(需后台保证返回前已解析)。前端不感知 pageId。 > 无论哪种方式,最终下发给前端的 `nav.path` 必须是 `/page/{slug}` 形态。 ### 3.3 关联/解绑时的数据一致性 - 单页被删除或 slug 变更时,应同步清理或更新引用它的导航 `nav.path`,避免产生死链(前端遇到无效 slug 会渲染空状态,但死链对 SEO 不友好)。 - 建议后台在单页管理列表页提供"已绑定菜单"反查,便于排查。 --- ## 4. 路由收敛规则(前端已落实,供后端理解) | 访问地址 | 行为 | |---|---| | `/page/{slug}` | 正常渲染 cms_page 单页内容(slug 非 about/contact) | | `/page/{数字}` | 旧逻辑:按 navigationId 取 cms_navigation 正文(兼容旧租户) | | `/page/about` | 301 → `/about`(独立富组件,规范地址) | | `/page/contact` | 301 → `/contact`(独立富组件,规范地址) | | `/about`、`/contact` | 直接渲染独立富组件 | --- ## 5. 待办(需前后端共同确认,前端暂未做) - **动态 sitemap**:当前站点地图未纳入 `cms_page` 的 slug。需后台提供"当前站点全部已发布单页 slug 列表"接口(或 site info 携带),前端再补充到 sitemap。 - **顶层兜底层清理**:`app/pages/[slug].vue` 旧兜底层可能与 `/page/{slug}` 产生 SEO 重复,后续建议收窄或移除(低优先级,不影响当前功能)。 --- ## 6. 对接自查清单 - [ ] 单页管理创建页面 → 生成唯一 SEO slug ✅ - [ ] 导航关联单页 → `nav.path` 输出为 `/page/{slug}` ✅ - [ ] slug 删除/变更 → 同步更新导航 path ✅ - [ ] 单页访问 → `/page/{slug}` 正常出内容 ✅ - [ ] about/contact 访问 → `/about`、`/contact`(非 `/page/about`)✅ - [ ] sitemap 是否需纳入 cms_page(待排期)⬜