feat(portal): 补入整站页脚,并让项目列表页不显示页脚
mirror-to-gitee / mirror (push) Successful in 4s

用户反馈 /projects/(项目列表)页底部的品牌/联系/版权区应该去掉。

背景:这几个文件此前一直未提交——远端仓库其实没有页脚,
PortalFooter.vue 只存在于本地,HEAD 版 index.ts 也没引用它。
所以本次把页脚整套补齐,再叠加「按页面决定是否展示」的逻辑。

新增/改动
- .vitepress/theme/components/PortalFooter.vue(新增,274 行)
  品牌区 + 产品体系/文档资源/关于我们/联系我们四栏 + 二维码浮层 + 版权条
- .vitepress/theme/styles/portal.css:补入全部 .pf-foot-* 样式(508 行)
  只搬运页脚相关规则,不夹带工作区里其它未提交的样式改动
- .vitepress/theme/index.ts:挂载页脚 + 页面级显隐判定
- pages/projects/index.md:frontmatter 加 footer: false

页脚显隐判定(isDocPage)
「文档型页面不挂页脚」——这类页面有左侧目录树、右侧本页目录、
底部上一页/下一页翻页,读者正在阅读流里,450px 的品牌收尾区是纯噪音。
命中任一条件即隐藏:
  1) 路径 /projects/<id>/manual/...
  2) frontmatter 有 sidebar / outline / aside
  3) frontmatter 显式 footer: false

frontmatter 的 footer 可双向覆盖(这解决了 /projects/ 的困境):
  该页有 outline: deep,按上面的规则本会被判成文档页而隐藏页脚,
  但它本质是「浏览页」,需要显式 footer: false 才符合预期。
  同理 footer: true 可强制显示。

验证(干净 clone 构建后实测)
- /projects/        无页脚(footer=false,无版权条)
- /                  有页脚(453px,渐变背景正常)
- 文档页(详情/对比/快速开始/手册)均无页脚
- 自定义整页(关于/联系/演示/官方文档)均有页脚
This commit is contained in:
Dai0814
2026-11-06 13:39:41 +08:00
parent dbe708511a
commit e4757446cf
4 changed files with 823 additions and 2 deletions
+38 -2
View File
@@ -1,6 +1,6 @@
import DefaultTheme from 'vitepress/theme'
import type { Theme } from 'vitepress'
import { h, watch, nextTick } from 'vue'
import { h, watch, nextTick, computed } from 'vue'
import { useData, useRoute } from 'vitepress'
import ProjectList from './components/ProjectList.vue'
@@ -8,6 +8,7 @@ import HomePage from './components/HomePage.vue'
import CapabilityTabs from './components/CapabilityTabs.vue'
import FeatureGrid from './components/FeatureGrid.vue'
import ScreenshotPreview from './components/ScreenshotPreview.vue'
import PortalFooter from './components/PortalFooter.vue'
import { setupNavAnchorHighlight, applyNavAnchorHighlight } from './nav-anchor'
@@ -24,6 +25,37 @@ const PortalLayout = () => {
const isPortal = frontmatter.value.layout === 'page'
/**
* 是否隐藏整站页脚。
*
* 判定原则:**文档型页面不挂页脚**。
* 这类页面有左侧目录树、右侧本页目录、底部上一页/下一页翻页,
* 读者正处在阅读流里,页脚那 450px 的品牌/联系/版权是纯噪音,
* 还会和翻页按钮挤在一起。
*
* 覆盖三种情况:
* 1) 路径命中项目手册 `/projects/<id>/manual/...`
* 2) frontmatter 写了 `sidebar` / `outline` / `aside`(文档页标记)
* 3) frontmatter 显式 `footer: false`
*
* frontmatter 的 `footer` 可双向覆盖:
* footer: false → 强制隐藏(如清单页 /projects/:有 outline 但本质是浏览页)
* footer: true → 强制显示
*
* 自定义整页(layout: page,如首页/关于/演示/官方文档)不在此列,
* 它们有完整的品牌收尾节奏,页脚保留。
*/
const isManualPath = computed(() => /^\/projects\/[^/]+\/manual(\/|$)/.test(route.path))
const isDocPage = computed(() => {
const fm = frontmatter.value as Record<string, unknown>
if (fm.layout === 'page' || fm.layout === 'home') return false
if (fm.footer === false) return true
if (fm.footer === true) return false
const hasDocMarks =
fm.sidebar !== undefined || fm.outline !== undefined || fm.aside !== undefined
return isManualPath.value || hasDocMarks
})
/**
* Layout 是函数式组件,onMounted 在这里不生效(Vue 会告警),
* 因此直接在渲染期间调度:等 DOM 落地后跑一次,再靠 MutationObserver 兜住后续变化。
@@ -38,7 +70,11 @@ const PortalLayout = () => {
() => nextTick(() => applyNavAnchorHighlight())
)
return h('div', { class: isPortal ? 'portal-page' : '' }, h(DefaultTheme.Layout))
return h('div', { class: isPortal ? 'portal-page' : '' }, h(DefaultTheme.Layout, null, {
// 自定义整站页脚(品牌 + 多栏链接 + 联系方式 + 版权条)
// 文档型页面一律不挂(见 isDocPage 判定)
'layout-bottom': isDocPage.value ? undefined : () => h(PortalFooter),
}))
}
export default {