Files
2026-05-18 17:29:18 +08:00

392 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 主题五大改进实施计划
## 任务一:Footer 配置组缺失
### 问题
[Footer.astro](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/src/components/Footer.astro) 引用了 `theme.config?.footer?.footer_copyright``footer_icp``footer_socials``footer_show_powered``footer_show_theme``footer_custom_html` 等配置项,但 [settings.yaml](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/settings.yaml) 中没有定义 footer 配置组,用户在后台无法设置页脚内容。
### 修改文件
- `settings.yaml` — 新增 footer 配置组
### 具体改动
在 settings.yaml 的 `comment` 配置组之后新增 `footer` 配置组:
```yaml
- group: footer
label: 页脚
formSchema:
- $formkit: text
name: footer_copyright
label: 版权信息(留空则使用默认格式 © 年份 站点标题)
- $formkit: text
name: footer_icp
label: ICP 备案号
- $formkit: repeater
name: footer_socials
label: 社交链接
children:
- $formkit: text
name: platform
label: 平台名称
- $formkit: text
name: icon
label: 图标类名(如 fa-brands fa-github
- $formkit: url
name: url
label: 链接地址
- $formkit: switch
name: footer_show_powered
label: 显示 "Powered by Halo"
value: true
- $formkit: switch
name: footer_show_theme
label: 显示主题版本
value: true
- $formkit: code
name: footer_custom_html
label: 自定义 HTML(统计代码等)
language: html
```
---
## 任务二:SEO Meta 标签严重缺失
### 问题
[Layout.astro](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/src/layouts/Layout.astro) 的 `<head>` 中只有全站 description,缺少 og 标签、canonical URL、RSS 链接等。文章页应使用文章摘要作为 description。
### 修改文件
- `src/layouts/Layout.astro` — 在 `<head>` 中添加 SEO meta 标签
- `src/pages/post.astro` — 在 head slot 中添加文章页专属 SEO 标签
- `src/pages/page.astro` — 在 head slot 中添加页面专属 SEO 标签
### 具体改动
#### Layout.astro — 全局 SEO 标签
在现有 `<meta name="description">` 之后添加:
```html
<meta name="keywords" th:content="${site.seo?.keywords}" />
<link rel="canonical" th:href="${site.url}" />
<link rel="alternate" type="application/rss+xml" th:title="${site.title}" th:href="@{/feed.xml}" />
<meta property="og:site_name" th:content="${site.title}" />
<meta property="og:type" content="website" />
<meta property="og:url" th:content="${site.url}" />
<meta property="og:title" th:content="${site.title}" />
<meta property="og:description" th:content="${site.seo?.description}" />
<meta name="twitter:card" content="summary" />
```
#### post.astro — 文章页专属 SEO 标签
`<Fragment slot="head">` 中,`<title>` 之后添加:
```html
<meta name="description" th:content="${post.spec.excerpt ?: site.seo?.description}" />
<link rel="canonical" th:href="${post.status.permalink}" />
<meta property="og:type" content="article" />
<meta property="og:title" th:content="${post.spec.title}" />
<meta property="og:description" th:content="${post.spec.excerpt ?: site.seo?.description}" />
<meta property="og:url" th:href="@{${post.status.permalink}}" />
<meta property="og:image" th:if="${post.spec.cover}" th:content="${post.spec.cover}" />
<meta property="article:published_time" th:content="${post.spec.publishTime}" />
<meta name="twitter:card" content="summary_large_image" th:if="${post.spec.cover}" />
<meta name="twitter:card" content="summary" th:unless="${post.spec.cover}" />
<meta name="twitter:title" th:content="${post.spec.title}" />
<meta name="twitter:description" th:content="${post.spec.excerpt ?: site.seo?.description}" />
<meta name="twitter:image" th:if="${post.spec.cover}" th:content="${post.spec.cover}" />
```
#### page.astro — 自定义页面专属 SEO 标签
`<Fragment slot="head">` 中,`<title>` 之后添加:
```html
<meta name="description" th:content="${singlePage.spec.excerpt ?: site.seo?.description}" />
<link rel="canonical" th:href="${singlePage.status.permalink}" />
<meta property="og:type" content="website" />
<meta property="og:title" th:content="${singlePage.spec.title}" />
<meta property="og:description" th:content="${singlePage.spec.excerpt ?: site.seo?.description}" />
<meta property="og:url" th:href="@{${singlePage.status.permalink}}" />
```
---
## 任务三:导航当前页面无高亮
### 问题
[Navbar.astro](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/src/components/Navbar.astro) 中 CSS 已定义 `.wi-navbar__link--active` 样式,但模板中没有为当前页面的导航链接添加 active 类名。
### 修改文件
- `src/components/Navbar.astro`
### 具体改动
在导航链接 `<a>` 标签上添加 `th:classappend` 条件判断,通过比较当前请求路径与菜单项链接来判断是否高亮:
```html
<a
th:each="menuItem : ${menu.menuItems}"
th:href="@{${menuItem.status.href}}"
th:target="${menuItem.spec.target}"
th:text="${menuItem.status.displayName}"
class="wi-navbar__link"
th:classappend="${#strings.equals(#request.requestURI, menuItem.status.href)} ? 'wi-navbar__link--active'"
>
</a>
```
同时需要在 MobileMenu.astro 中也添加同样的高亮逻辑。MobileMenu.astro 第 16-22 行的导航链接结构与 Navbar 相同:
```html
<a
th:each="menuItem : ${menu.menuItems}"
th:href="@{${menuItem.status.href}}"
th:target="${menuItem.spec.target}"
th:text="${menuItem.status.displayName}"
class="wi-mobile-menu__link"
th:classappend="${#strings.equals(#request.requestURI, menuItem.status.href)} ? 'wi-mobile-menu__link--active'"
></a>
```
并在 MobileMenu.astro 的 `<style>` 中添加 active 样式:
```css
.wi-mobile-menu__link--active {
color: var(--accent);
background: var(--bg-raised);
font-weight: 600;
}
```
---
## 任务四:移动端文章目录不可用(浮动目录按钮)
### 问题
[post.astro](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/src/pages/post.astro) 中 TOC 仅在 `min-width: 1280px` 时显示,移动端没有任何替代方案。
### 修改文件
- `src/pages/post.astro`
### 具体改动
#### 1. 添加移动端浮动 TOC 按钮
在文章 `<article>` 内添加一个浮动按钮,仅在 `max-width: 1279px` 时显示:
```html
<button
th:if="${theme.config?.article?.article_show_toc ?: true}"
class="wi-toc-fab"
id="wi-toc-fab"
type="button"
aria-label="打开目录"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></svg>
</button>
```
#### 2. 添加移动端 TOC 抽屉面板
在浮动按钮之后添加一个从底部滑出的抽屉面板:
```html
<div
th:if="${theme.config?.article?.article_show_toc ?: true}"
class="wi-toc-drawer"
id="wi-toc-drawer"
>
<div class="wi-toc-drawer__overlay"></div>
<div class="wi-toc-drawer__panel">
<div class="wi-toc-drawer__header">
<span class="wi-toc-drawer__title">目录</span>
<button class="wi-toc-drawer__close" type="button" aria-label="关闭目录">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
</button>
</div>
<nav class="wi-toc-drawer__nav" id="wi-toc-drawer-nav"></nav>
</div>
</div>
```
#### 3. 添加 CSS 样式
```css
.wi-toc-fab {
display: none;
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
width: 44px;
height: 44px;
border-radius: 50%;
border: 1px solid var(--rule);
background: var(--bg-raised);
color: var(--ink-2);
cursor: pointer;
z-index: 20;
align-items: center;
justify-content: center;
box-shadow: var(--shadow-md);
transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.wi-toc-fab:hover {
color: var(--accent);
border-color: var(--accent);
}
@media (max-width: 1279px) {
.wi-toc-fab {
display: inline-flex;
}
}
.wi-toc-drawer {
display: none;
}
.wi-toc-drawer--open {
display: block;
}
.wi-toc-drawer__overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 50;
}
.wi-toc-drawer__panel {
position: fixed;
bottom: 0;
left: 0;
right: 0;
max-height: 60vh;
background: var(--bg);
border-top: 1px solid var(--rule);
border-radius: 16px 16px 0 0;
padding: 1.25rem;
z-index: 51;
overflow-y: auto;
transform: translateY(0);
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.wi-toc-drawer__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--rule);
}
.wi-toc-drawer__title {
font-family: var(--font-sans);
font-size: var(--text-sm);
font-weight: 600;
color: var(--ink);
}
.wi-toc-drawer__close {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: none;
background: none;
color: var(--ink-3);
cursor: pointer;
}
.wi-toc-drawer__close:hover {
color: var(--accent);
}
.wi-toc-drawer__nav {
display: flex;
flex-direction: column;
gap: 2px;
}
.wi-toc-drawer__nav .wi-toc__link {
font-size: var(--text-sm);
padding: 6px 0;
}
```
#### 4. 添加 JS 逻辑
在现有 `<script is:inline>` 中,TOC 构建逻辑之后,添加移动端抽屉逻辑:
```javascript
var tocFab = document.getElementById("wi-toc-fab");
var tocDrawer = document.getElementById("wi-toc-drawer");
var tocDrawerNav = document.getElementById("wi-toc-drawer-nav");
if (tocFab && tocDrawer && tocDrawerNav && tocNav) {
tocDrawerNav.innerHTML = tocNav.innerHTML;
tocFab.addEventListener("click", function () {
tocDrawer.classList.add("wi-toc-drawer--open");
document.body.style.overflow = "hidden";
});
var drawerClose = tocDrawer.querySelector(".wi-toc-drawer__close");
var drawerOverlay = tocDrawer.querySelector(".wi-toc-drawer__overlay");
function closeDrawer() {
tocDrawer.classList.remove("wi-toc-drawer--open");
document.body.style.overflow = "";
}
if (drawerClose) drawerClose.addEventListener("click", closeDrawer);
if (drawerOverlay) drawerOverlay.addEventListener("click", closeDrawer);
tocDrawerNav.querySelectorAll(".wi-toc__link").forEach(function (link) {
link.addEventListener("click", function () {
closeDrawer();
});
});
}
```
---
## 任务五:404/500 页面深色模式不生效
### 问题
[404.html](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/public/error/404.html) 和 [500.html](file:///c:/Users/Zhang/Documents/Halo/WarmIsland/public/error/500.html) 是纯静态页面,没有读取 localStorage 中的主题偏好,首次直接访问错误页面时深色模式不会生效。
### 修改文件
- `public/error/404.html`
- `public/error/500.html`
### 具体改动
在两个文件的 `<head>` 中,`<style>` 标签之前,添加与 Layout.astro 相同的主题检测脚本(简化版,仅检测 localStorage 和系统偏好):
```html
<script>
(function () {
var stored = localStorage.getItem("wi-theme");
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
var isDark = stored === "dark" || (!stored && prefersDark);
if (isDark) {
document.documentElement.classList.add("dark");
}
})();
</script>
```
这段脚本会在页面渲染前检测用户的主题偏好并添加 `dark` 类名,确保 CSS 变量正确切换。
---
## 执行顺序
1. **settings.yaml** — 新增 footer 配置组
2. **Layout.astro** — 添加全局 SEO meta 标签
3. **post.astro** — 添加文章页 SEO 标签 + 移动端 TOC 浮动按钮和抽屉
4. **page.astro** — 添加页面 SEO 标签
5. **Navbar.astro** — 添加导航当前页面高亮
6. **MobileMenu.astro** — 添加导航当前页面高亮(需先确认结构)
7. **404.html** — 添加深色模式检测脚本
8. **500.html** — 添加深色模式检测脚本
9. 构建并部署到 Docker 验证