现象:导航左上角显示成「雪羊科技物联网卡与设备管理平台」挤在一行, 副标题没有换行,还压到了 logo 上。 根因 siteTitle 里的副标题是 <span class="site-subtitle">,经 v-html 插入后, 其父级是 VitePress 自己的**裸 <span>(无 class)**,而不是 .title-text。 原样式写的是 `.VPNavBarTitle .title-text .site-subtitle`, 选择器永远匹配不上,display:block 从未生效,副标题只能行内跟随。 改动 - 选择器改为 .VPNavBarTitle .site-subtitle(去掉不存在的 .title-text) - 品牌名与副标题的容器改为 flex 纵向 + 垂直居中, 整体在导航高度内居中 - 副标题 11px / 0.03em 字距 / var(--p-ink-3) 弱化; 品牌名与副标题间距 3px - 响应式:≤860px 副标题缩到 10.5px;≤480px 隐藏副标题只留品牌名 - 新增 scripts/check-nav-brand.mjs 并接入 npm run check(prebuild/predev 自动跑): 校验 siteTitle 的**品牌主体**必须是「雪羊科技」(允许带副标题 span), 且 logo 配置与文件都存在。 反例全部验证:改成「雪羊开源」→ 拦;只留「雪羊科技」→ 通过; 改成「雪羊科技开源」→ 拦;删掉 siteTitle → 拦 验证 - 干净副本构建后实测三档宽度: 1440/860 → 「雪羊科技 ⏎ 物联网卡与设备管理平台」,display:block 390 → 只显示「雪羊科技」,副标题 display:none - 品牌区截图确认两行居中、不压 logo
This commit is contained in:
@@ -63,6 +63,18 @@ export default defineConfig({
|
|||||||
['link', { rel: 'icon', type: 'image/svg+xml', href: `${SITE_BASE}favicon.svg` }],
|
['link', { rel: 'icon', type: 'image/svg+xml', href: `${SITE_BASE}favicon.svg` }],
|
||||||
],
|
],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
|
/**
|
||||||
|
* 导航左上角的品牌名 —— 主体固定为「雪羊科技」,不要替换成别的字。
|
||||||
|
*
|
||||||
|
* 后面那截 <span class="site-subtitle">物联网卡与设备管理平台</span>
|
||||||
|
* 是品牌定位副标题(样式见 portal.css 的 .site-subtitle),
|
||||||
|
* 与品牌名一起构成左上角的两行结构:上行品牌、下行定位。
|
||||||
|
*
|
||||||
|
* 注意区分:
|
||||||
|
* config.title → 浏览器标签页与 SEO 用的完整站名,不显示在导航
|
||||||
|
* siteTitle → 左上角实际渲染的内容
|
||||||
|
* 校验见 scripts/check-nav-brand.mjs(构建前自动执行)。
|
||||||
|
*/
|
||||||
siteTitle: '雪羊科技<span class="site-subtitle">物联网卡与设备管理平台</span>',
|
siteTitle: '雪羊科技<span class="site-subtitle">物联网卡与设备管理平台</span>',
|
||||||
logo: { src: '/snowgoat-logo.png', alt: '雪羊科技' },
|
logo: { src: '/snowgoat-logo.png', alt: '雪羊科技' },
|
||||||
nav: [
|
nav: [
|
||||||
|
|||||||
@@ -1075,3 +1075,50 @@ html.portal-nav-home .VPNavBarMenuLink.active:not([data-anchor-active]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================================
|
||||||
|
导航左上角品牌区:两行结构
|
||||||
|
第一行:雪羊科技(品牌名)
|
||||||
|
第二行:物联网卡与设备管理平台(定位副标题,更弱)
|
||||||
|
siteTitle 里的副标题是 <span class="site-subtitle">,由 v-html 插入。
|
||||||
|
注意:它的父级是 VitePress 自己的裸 <span>(无 class),
|
||||||
|
所以选择器不能写 .title-text .site-subtitle —— 那个类根本不存在。
|
||||||
|
直接用 .VPNavBarTitle .site-subtitle 即可。
|
||||||
|
============================================================ */
|
||||||
|
.VPNavBarTitle .title {
|
||||||
|
line-height: 1.2;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 品牌名与副标题的容器:两行紧凑排列,整体垂直居中 */
|
||||||
|
.VPNavBarTitle .title > span {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1.15;
|
||||||
|
/* 品牌名与副标题作为一个整体在导航高度内垂直居中 */
|
||||||
|
height: var(--vp-nav-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.VPNavBarTitle .site-subtitle {
|
||||||
|
display: block;
|
||||||
|
margin-top: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
line-height: 1.25;
|
||||||
|
color: var(--p-ink-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px) {
|
||||||
|
.VPNavBarTitle .site-subtitle {
|
||||||
|
font-size: 10.5px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 窄屏下副标题可能挤压,超窄时隐藏,只留品牌名 */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.VPNavBarTitle .site-subtitle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"dev": "vitepress dev . --host 127.0.0.1",
|
"dev": "vitepress dev . --host 127.0.0.1",
|
||||||
"build": "vitepress build .",
|
"build": "vitepress build .",
|
||||||
"preview": "vitepress preview . --host 127.0.0.1",
|
"preview": "vitepress preview . --host 127.0.0.1",
|
||||||
"check": "node scripts/check-registry.mjs",
|
"check": "node scripts/check-registry.mjs && node scripts/check-nav-brand.mjs",
|
||||||
"prebuild": "npm run check",
|
"prebuild": "npm run check",
|
||||||
"predev": "npm run check"
|
"predev": "npm run check"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* 校验导航左上角品牌名。
|
||||||
|
*
|
||||||
|
* 约定:themeConfig.siteTitle 必须以「雪羊科技」为主体。
|
||||||
|
*
|
||||||
|
* 允许的形态:
|
||||||
|
* 雪羊科技
|
||||||
|
* 雪羊科技<span class="site-subtitle">物联网卡与设备管理平台</span>
|
||||||
|
*
|
||||||
|
* 不允许:
|
||||||
|
* - 主体被换成别的品牌名(如「雪羊科技开源」「雪羊开源」)
|
||||||
|
* - 整个删掉 siteTitle(VitePress 会回落到 config.title 的超长站名)
|
||||||
|
* - logo 缺失或指向不存在的文件
|
||||||
|
*
|
||||||
|
* config.title 是浏览器标签页/SEO 用的完整站名,和这里不是一回事。
|
||||||
|
*/
|
||||||
|
import { readFileSync, existsSync } from 'node:fs'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { dirname, join } from 'node:path'
|
||||||
|
|
||||||
|
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
||||||
|
const configPath = join(root, '.vitepress', 'config.mts')
|
||||||
|
const src = readFileSync(configPath, 'utf-8')
|
||||||
|
|
||||||
|
/** 品牌名主体,左上角必须以此开头 */
|
||||||
|
const BRAND = '雪羊科技'
|
||||||
|
|
||||||
|
// 取 siteTitle 的赋值(单引号或双引号,内容可含 HTML)
|
||||||
|
const m = src.match(/siteTitle\s*:\s*(['"])([\s\S]*?)\1\s*,/)
|
||||||
|
if (!m) {
|
||||||
|
console.error('[nav-brand] themeConfig.siteTitle 缺失。')
|
||||||
|
console.error(` 左上角会回落到 config.title(完整长名),应显式设为「${BRAND}」。`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = m[2].trim()
|
||||||
|
|
||||||
|
// 去掉可选的副标题 span,只看品牌主体
|
||||||
|
const withoutSubtitle = raw.replace(
|
||||||
|
/<span\s+class="site-subtitle"[^>]*>[\s\S]*?<\/span>/g,
|
||||||
|
''
|
||||||
|
).trim()
|
||||||
|
|
||||||
|
if (withoutSubtitle !== BRAND) {
|
||||||
|
console.error(`[nav-brand] siteTitle 的品牌主体是「${withoutSubtitle}」,应为「${BRAND}」。`)
|
||||||
|
console.error(' 左上角品牌名固定,副标题可保留但主体不要换。')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// logo 检查:既要配置在,也要文件真的存在
|
||||||
|
const logoNeedle = 'snowgoat-logo.png'
|
||||||
|
if (!src.includes(logoNeedle)) {
|
||||||
|
console.error(`[nav-brand] 未找到 logo 配置 ${logoNeedle}。`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const logoFile = join(root, 'pages', 'public', logoNeedle)
|
||||||
|
if (!existsSync(logoFile)) {
|
||||||
|
console.error(`[nav-brand] logo 文件不存在:pages/public/${logoNeedle}`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasSubtitle = /site-subtitle/.test(raw)
|
||||||
|
console.log(
|
||||||
|
`[nav-brand] OK:左上角「${BRAND}」${hasSubtitle ? ' + 定位副标题' : ''} + ${logoNeedle}`
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user