Hugo系统文章多层分类设计方法

1. 什么是多层分类?

在博客文章管理中,多层分类(Hierarchical Categories)是指将分类按照层级关系组织,类似于文件夹的树状结构:

机械设计(主分类)
├── 压力容器设计(子分类)
├── 仿真分析(子分类)
└── 传动系统(子分类)

技术教程(主分类)
├── 编程开发(子分类)
└── 开发工具(子分类)

1.1 为什么需要多层分类?

  • 文章数量增多:平铺所有分类会显得杂乱无章
  • 主题细分:同一大类下有多个细分领域
  • 导航便利:读者可以按层级浏览感兴趣的内容
  • 结构清晰:便于长期维护和管理

2. 实现原理

Hugo本身不直接支持树状分类,但我们可以通过命名约定自定义模板实现多层分类效果:

2.1 核心思路

使用 主分类/子分类 的格式来表示层级关系:

这样Hugo会创建两个分类页面:

  • /categories/机械设计/
  • /categories/机械设计/压力容器设计/

然后通过自定义模板解析这种命名规则,在分类列表页展示层级关系。

3. 实现步骤

步骤1:配置Hugo支持分类

编辑 hugo.toml 文件,添加taxonomies配置:

# 配置分类法(支持多级分类)
[taxonomies]
  category = "categories"
  tag = "tags"
  series = "series"

步骤2:修改文章Front Matter

在文章的front matter中使用数组形式定义分类:

示例1:压力容器设计类文章

+++
title = '分析设计法介绍'
date = '2026-01-24T19:10:38+01:00'
draft = false

# 同时属于"机械设计"和"机械设计/压力容器设计"

tags = ["压力容器", "分析设计", "DBA"]
summary = "这是一篇关于承压设备分析设计的入门简介..."
+++

示例2:编程教程类文章

+++
title = 'Python科学计算入门'
date = '2026-01-20T16:30:00+01:00'
draft = false


tags = ["Python", "NumPy", "编程", "科学计算"]
+++

步骤3:创建自定义分类模板

创建 layouts/_default/terms.html 文件:

{{- define "main" }}

{{- if .Title }}
<header class="page-header">
    <h1>{{ .Title }}</h1>
    {{- if .Description }}
    <div class="post-description">
        {{ .Description }}
    </div>
    {{- end }}
</header>
{{- end }}

{{- $type := .Type }}
{{- $terms := .Data.Terms }}

{{- /* 收集所有分类并分组 */ -}}
{{- $mainCategories := slice }}
{{- $subCategories := dict }}
{{- $categoryCount := dict }}

{{- range $key, $value := $terms.Alphabetical }}
  {{- $name := .Name }}
  {{- $count := .Count }}
  {{- $categoryCount = merge $categoryCount (dict $name $count) }}
  
  {{- if not (strings.Contains $name "/") }}
    {{- $mainCategories = $mainCategories | append $name }}
  {{- else }}
    {{- $parts := split $name "/" }}
    {{- $parent := index $parts 0 }}
    {{- $subs := index $subCategories $parent | default slice }}
    {{- $subs = $subs | append $name }}
    {{- $subCategories = merge $subCategories (dict $parent $subs) }}
  {{- end }}
{{- end }}

<div class="terms">
  {{- range sort $mainCategories }}
    {{- $mainCat := . }}
    {{- $count := index $categoryCount $mainCat }}
    {{- with site.GetPage (printf "/%s/%s" $type $mainCat) }}
      {{- $mainCatURL := .Permalink }}
      
      <div class="category-group">
        <h2 class="main-category">
          <a href="{{ $mainCatURL }}">{{ $mainCat }}</a>
          <sup><strong>{{ $count }}</strong></sup>
        </h2>
        
        {{- /* 显示该主分类下的子分类 */ -}}
        {{- $subs := index $subCategories $mainCat }}
        {{- if $subs }}
        <ul class="sub-categories">
          {{- range sort $subs }}
            {{- $subCat := . }}
            {{- $subCount := index $categoryCount $subCat }}
            {{- $parts := split $subCat "/" }}
            {{- $subName := index $parts 1 }}
            {{- with site.GetPage (printf "/%s/%s" $type $subCat) }}
              <li>
                <a href="{{ .Permalink }}">{{ $subName }}</a>
                <sup>{{ $subCount }}</sup>
              </li>
            {{- end }}
          {{- end }}
        </ul>
        {{- end }}
      </div>
    {{- end }}
  {{- end }}
</div>

{{- end }}{{/* end main */}}

步骤4:添加CSS样式

创建 assets/css/extended/category-hierarchy.css 文件:

/* 多级分类样式 */
.category-group {
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
}

.category-group:last-child {
  border-bottom: none;
}

.main-category {
  font-size: 1.5rem;
  margin-bottom: 0.8rem;
  color: var(--primary);
}

.main-category a {
  color: var(--primary);
  text-decoration: none;
}

.main-category a:hover {
  text-decoration: underline;
}

.main-category sup {
  font-size: 0.8rem;
  margin-left: 0.3rem;
  color: var(--secondary);
}

.sub-categories {
  list-style: none;
  padding-left: 2rem;
  margin: 0;
}

.sub-categories li {
  margin: 0.5rem 0;
  font-size: 1.1rem;
}

.sub-categories li a {
  color: var(--content);
  text-decoration: none;
  transition: color 0.3s ease;
}

.sub-categories li a:hover {
  color: var(--primary);
  text-decoration: underline;
}

.sub-categories li sup {
  font-size: 0.75rem;
  margin-left: 0.3rem;
  color: var(--secondary);
}

/* 移动端适配 */
@media (max-width: 768px) {
  .sub-categories {
    padding-left: 1rem;
  }
  
  .main-category {
    font-size: 1.3rem;
  }
  
  .sub-categories li {
    font-size: 1rem;
  }
}

步骤5:测试效果

运行Hugo服务器:

hugo server -D

访问 http://localhost:1313/categories/ 查看分类页面效果。

4. 模板代码详解

4.1 核心逻辑

{{- $type := .Type }}              // 获取类型(categories/tags)
{{- $terms := .Data.Terms }}        // 获取所有分类数据

// 判断是否为子分类(包含"/")
{{- if not (strings.Contains $name "/") }}
    // 主分类
{{- else }}
    // 子分类,分割字符串获取父分类名
    {{- $parts := split $name "/" }}
    {{- $parent := index $parts 0 }}
{{- end }}

4.2 数据结构

模板维护三个数据结构:

  1. $mainCategories:主分类列表 ["机械设计", "技术教程"]
  2. $subCategories:子分类字典
    {
      "机械设计": ["机械设计/压力容器设计", "机械设计/仿真分析"],
      "技术教程": ["技术教程/编程开发"]
    }
    
  3. $categoryCount:每个分类的文章数量

4.3 渲染流程

  1. 遍历所有主分类
  2. 显示主分类名称和文章数量
  3. 查找该主分类下的所有子分类
  4. 缩进显示子分类列表

5. 目录组织建议

5.1 按分类组织文件夹(推荐)

content/posts/
├── 机械设计/
│   ├── 分析设计法介.md
│   ├── 有限元分析基础.md
│   └── 齿轮设计计算.md
├── 压力容器/
│   ├── LBB技术.md
│   └── ASME规范设计.md
└── 技术教程/
    ├── Python科学计算.md
    └── Git版本控制.md

这样做的好处:

  • 文件管理更直观
  • 便于批量操作
  • 与分类逻辑一致

5.2 分类命名规范

主分类建议

  • 宽泛的领域名称
  • 2-4个字为宜
  • 例如:机械设计、技术教程、生活随笔

子分类建议

  • 具体的主题方向
  • 3-6个字为宜
  • 例如:压力容器设计、编程开发、开发工具

6. 常见问题

Q1: 文章必须同时属于主分类和子分类吗?

是的。为了让文章在主分类页面也能显示,需要同时指定:

Q2: 可以有多层嵌套吗(如三层)?

可以,但不推荐。两层分类已经足够清晰,过深的层级会增加复杂度:

# 理论上可行但不推荐

Q3: 子分类可以属于多个主分类吗?

不建议。为保持层级清晰,每个子分类应该只属于一个主分类。

Q4: 如何修改现有文章的分类?

批量修改可以使用脚本或文本编辑器的查找替换功能:

查找:

替换为:

Q5: PaperMod主题如何自动加载CSS?

PaperMod主题会自动加载 assets/css/extended/ 目录下的所有CSS文件,无需额外配置。

7. 高级技巧

7.1 自动统计主分类文章数

如果希望主分类的文章数包括所有子分类的文章,可以在模板中计算:

{{- $totalCount := $count }}
{{- $subs := index $subCategories $mainCat }}
{{- range $subs }}
  {{- $subCount := index $categoryCount . }}
  {{- $totalCount = add $totalCount $subCount }}
{{- end }}

7.2 添加分类图标

在CSS中为不同分类添加图标:

.main-category a::before {
  content: "📁 ";
}

.sub-categories li a::before {
  content: "📄 ";
}

7.3 折叠/展开子分类

添加JavaScript实现交互:

document.querySelectorAll('.main-category').forEach(function(cat) {
  cat.addEventListener('click', function() {
    const subList = this.nextElementSibling;
    subList.classList.toggle('collapsed');
  });
});

8. 完整示例

项目结构

myblog/
├── hugo.toml                          # Hugo配置
├── content/
│   └── posts/
│       ├── 机械设计/
│       │   └── 文章1.md
│       └── 技术教程/
│           └── 文章2.md
├── layouts/
│   └── _default/
│       └── terms.html                 # 分类模板
└── assets/
    └── css/
        └── extended/
            └── category-hierarchy.css  # 样式文件

文章示例

+++
title = '有限元分析基础'
date = '2026-01-15T10:30:00+01:00'
draft = false
tags = ["有限元", "FEA", "ANSYS"]
summary = "介绍有限元分析的基本原理..."
+++

# 文章内容
...

9. 最佳实践

  1. 分类不宜过多:主分类3-5个,每个主分类下2-4个子分类
  2. 命名统一规范:使用中文或英文,保持一致
  3. 定期整理:随着内容增加,适时调整分类结构
  4. 避免重复:同一主题不要创建多个相似分类
  5. 保持灵活:分类不是一成不变的,可以根据需要调整

10. 总结

多层分类系统让Hugo博客的内容组织更加清晰有序。通过:

  1. ✅ 使用 主分类/子分类 命名约定
  2. ✅ 自定义terms.html模板解析层级
  3. ✅ 添加CSS美化展示效果
  4. ✅ 在front matter中正确配置分类

就能实现一个功能完善的多层分类系统。

11. 参考资源


希望这篇教程能帮助你更好地组织博客内容!如有问题,欢迎交流。