Hugo Stack 主题页脚统计和访问量集成
本文详细记录 Hugo Stack 主题的页脚统计功能(文章统计、运行时间统计)和 busuanzi 访问量统计的集成方法。
概述
本次集成主要涉及三个方面:
- 文章统计:显示文章总数和总字数(格式:x 万 x 千字)
- 运行时间统计:显示网站运行时间(格式:x 年 x 月 x 天),起始时间为第一篇文章的发布日期
- busuanzi 访问量统计:集成不蒜子统计,显示站点访问量、访客数和文章阅读量
1. 页脚统计功能
1.1 需求说明
在页脚添加两个统计功能:
- 文章统计:显示文章总数和总字数(格式:x 万 x 千字)
- 运行时间统计:显示网站运行时间(格式:x 年 x 月 x 天),起始时间为第一篇文章的发布日期
1.2 配置说明
在 themes/hugo-theme-stack/hugo.yaml 的 footer 字段中添加两个开关:
params:
footer:
since: 2010
customText: <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" >陕ICP备20000710号</a>
showStats: true # 文章统计开关
showRuntime: true # 运行时间统计开关配置项说明:
showStats: 控制是否显示文章统计(文章数和总字数)showRuntime: 控制是否显示运行时间统计- 两个开关独立控制,可以单独启用或禁用
1.3 实现方案
修改 themes/hugo-theme-stack/layouts/partials/footer/footer.html 文件,在 customText 之后添加统计功能:
{{ with .Site.Params.footer.customText }}
{{ . | safeHTML }} <br/>
{{ end }}
{{ if .Site.Params.footer.showRuntime }}
{{ $posts := where .Site.RegularPages "Section" "post" }}
{{ if $posts }}
{{ $firstPost := index (sort $posts "Date" "asc") 0 }}
{{ $startDate := $firstPost.Date }}
{{ $now := now }}
{{ $totalSeconds := sub $now.Unix $startDate.Unix }}
{{ $totalDays := div $totalSeconds 86400 }}
{{ $years := div $totalDays 365 }}
{{ $remainingDays := mod $totalDays 365 }}
{{ $months := div $remainingDays 30 }}
{{ $days := mod $remainingDays 30 }}
本站已运行{{ $years }}年{{ $months }}月{{ $days }}天
<br/>
{{ end }}
{{ end }}
{{ if .Site.Params.footer.showStats }}
{{ $scratch := newScratch }}
{{ range (where .Site.Pages "Kind" "page" )}}
{{ $scratch.Add "total" .WordCount }}
{{ end }}
{{ $totalWords := $scratch.Get "total" }}
{{ $tenThousands := div $totalWords 10000 }}
{{ $remainingThousands := mod (div $totalWords 1000) 10 }}
发表了{{ len (where .Site.RegularPages "Section" "post") }}篇文章 ·
总计{{ $tenThousands }}万{{ $remainingThousands }}千字
<br/>
{{ end }}1.4 功能说明
1.4.1 运行时间统计(showRuntime)
实现逻辑:
- 获取所有
post分区的文章:where .Site.RegularPages "Section" "post" - 按发布日期升序排序:
sort $posts "Date" "asc" - 获取第一篇文章:
index ... 0 - 使用第一篇文章的发布日期作为起始时间:
$firstPost.Date - 计算与当前日期的差值,转换为年、月、天
显示格式:
本站已运行X年X月X天- 如果没有文章,则不显示
计算方式:
- 使用 Unix 时间戳计算总秒数
- 转换为总天数(86400 秒 = 1 天)
- 年数 = 总天数 ÷ 365
- 剩余天数 = 总天数 % 365
- 月数 = 剩余天数 ÷ 30
- 天数 = 剩余天数 % 30
1.4.2 文章统计(showStats)
实现逻辑:
- 遍历所有页面(
where .Site.Pages "Kind" "page") - 累加所有页面的字数(
WordCount) - 统计
post分区的文章数量 - 将总字数格式化为"万"和"千"单位
显示格式:
发表了X篇文章 · 总计X万X千字
字数格式化:
- 万位数 = 总字数 ÷ 10000
- 千位数 = (总字数 ÷ 1000) % 10
示例:
- 如果总字数为 12345,则显示:
总计1万2千字 - 如果总字数为 56789,则显示:
总计5万6千字
1.5 显示位置
统计信息显示在页脚的 powerby 部分,顺序为:
customText(自定义文本,如备案信息)showRuntime(运行时间统计)showStats(文章统计)- 主题信息(Built with Hugo, Designed by Jimmy)
1.6 使用示例
启用所有统计功能:
params:
footer:
showStats: true
showRuntime: true只启用文章统计:
params:
footer:
showStats: true
showRuntime: false只启用运行时间统计:
params:
footer:
showStats: false
showRuntime: true禁用所有统计功能:
params:
footer:
showStats: false
showRuntime: false1.7 注意事项
运行时间统计:
- 如果没有文章,运行时间统计不会显示
- 起始时间自动使用第一篇文章的发布日期,无需手动配置
文章统计:
- 统计所有页面的字数(包括非文章页面)
- 只统计
post分区的文章数量
性能考虑:
- 统计功能在构建时计算,不影响运行时性能
- 使用
newScratch进行累加计算,效率较高
2. busuanzi 访问量统计集成
2.1 需求说明
集成不蒜子(busuanzi)统计服务,实现:
- 站点统计:在页脚显示总访问量和总访客数
- 文章统计:在文章详情页显示文章阅读量
- 数字格式化:大于 1000 的数字自动转换为 k 格式(如 1500 → 1.5k)
2.2 配置说明
在 themes/hugo-theme-stack/hugo.yaml 中添加 busuanzi 配置:
params:
busuanzi:
enabled: true
article:
enabled: true
footer:
enabled: true配置项说明:
busuanzi.enabled: 总开关,控制是否启用 busuanzibusuanzi.article.enabled: 控制文章页是否显示访问量busuanzi.footer.enabled: 控制页脚是否显示站点统计
2.3 实现方案
2.3.1 加载 busuanzi 脚本
创建 layouts/partials/google_analytics.html 文件:
{{ if .Site.Params.busuanzi.enabled }}
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
{{ end }}2.3.2 页脚站点统计
修改 themes/hugo-theme-stack/layouts/partials/footer/footer.html,在 showStats 之后添加:
{{ if and .Site.Params.busuanzi.enabled .Site.Params.busuanzi.footer.enabled }}
总访问量<span id="busuanzi_value_site_pv">0</span>次,总访客数<span id="busuanzi_value_site_uv">0</span>人
<br/>
{{ end }}2.3.3 文章访问量显示
修改 themes/hugo-theme-stack/layouts/partials/article/components/details.html,在 article-time footer 中添加:
{{- if and .Site.Params.busuanzi.enabled .Site.Params.busuanzi.article.enabled -}}
<div class="article-views" style="display: none;">
<span id="busuanzi_value_page_pv">0</span> 次阅读
</div>
{{- end -}}2.3.4 数字格式化脚本
修改 themes/hugo-theme-stack/layouts/partials/footer/components/script.html,添加格式化脚本:
{{- if .Site.Params.busuanzi.enabled -}}
<script>
// 格式化数字,大于1000显示为k
(function() {
function formatBusuanzi(value) {
if (!value) return '0';
// 如果已经是格式化后的值(包含k),直接返回
if (value.toString().includes('k')) return value;
var num = parseInt(value);
if (isNaN(num)) return value;
if (num >= 1000) {
return (num / 1000).toFixed(1) + 'k';
}
return num.toString();
}
// 格式化单个元素
function formatElement(elementId) {
var element = document.getElementById(elementId);
if (!element) return;
// 检查是否已经格式化过(通过 data-formatted 属性)
if (element.hasAttribute('data-formatted')) {
return;
}
var originalText = element.textContent.trim();
// 只处理纯数字,且不是0(0可能是初始值,需要等待 busuanzi 更新)
if (originalText && /^\d+$/.test(originalText) && originalText !== '0') {
var formatted = formatBusuanzi(originalText);
if (formatted !== originalText) {
element.textContent = formatted;
element.setAttribute('data-formatted', 'true');
// 显示元素(如果之前是隐藏的)
if (element.style.display === 'none') {
element.style.display = '';
}
} else {
element.setAttribute('data-formatted', 'true');
if (element.style.display === 'none') {
element.style.display = '';
}
}
} else if (originalText === '0') {
// 如果是0,保持隐藏,等待 busuanzi 更新
element.style.display = 'none';
}
}
// 使用轮询方式检查并格式化,避免阻塞页面
function initBusuanziFormatter() {
var checkCount = 0;
var maxChecks = 50; // 最多检查50次(5秒)
var checkInterval = setInterval(function() {
// 格式化站点统计
formatElement('busuanzi_value_site_pv');
formatElement('busuanzi_value_site_uv');
// 格式化文章访问量(只在单页显示,列表页通过 CSS 隐藏)
var pagePv = document.getElementById('busuanzi_value_page_pv');
if (pagePv) {
formatElement('busuanzi_value_page_pv');
// 如果值不是0,显示容器
var container = pagePv.closest('.article-views');
if (container && pagePv.textContent.trim() !== '0') {
container.style.display = '';
}
}
checkCount++;
if (checkCount >= maxChecks) {
clearInterval(checkInterval);
}
}, 100); // 每100ms检查一次
}
// 页面加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initBusuanziFormatter);
} else {
initBusuanziFormatter();
}
})();
</script>
{{- end -}}2.3.5 隐藏列表页访问量
在 themes/hugo-theme-stack/assets/scss/partials/article.scss 中添加 CSS 规则,隐藏列表页中的访问量:
.article-list--compact {
// ... 其他样式 ...
.article-views {
display: none !important;
}
}2.4 功能说明
2.4.1 站点统计
显示位置:页脚 showStats 之后
显示内容:
- 总访问量:站点所有页面的访问次数总和
- 总访客数:访问站点的独立访客数
显示格式:
总访问量X次,总访客数X人- 数字大于 1000 时自动转换为 k 格式
2.4.2 文章访问量
显示位置:文章详情页的 article-time footer 中
显示内容:
- 当前文章的阅读次数
显示格式:
X 次阅读- 数字大于 1000 时自动转换为 k 格式
- 初始值 0 时隐藏,数据加载后显示
注意事项:
- 列表页中不显示访问量(通过 CSS 隐藏)
- 只在文章详情页显示
2.4.3 数字格式化
格式化规则:
- 小于 1000:显示原数字(如 999)
- 大于等于 1000:转换为 k 格式(如 1500 → 1.5k,10000 → 10.0k)
防止重复格式化:
- 使用
data-formatted属性标记已格式化的元素 - 检查值是否已包含 ‘k’,避免重复格式化
2.5 显示位置
统计信息显示顺序:
customText(自定义文本)showRuntime(运行时间统计)showStats(文章统计)- busuanzi 站点统计(总访问量、总访客数)
- 主题信息
2.6 使用示例
启用所有 busuanzi 功能:
params:
busuanzi:
enabled: true
article:
enabled: true
footer:
enabled: true只启用站点统计:
params:
busuanzi:
enabled: true
article:
enabled: false
footer:
enabled: true只启用文章访问量:
params:
busuanzi:
enabled: true
article:
enabled: true
footer:
enabled: false2.7 注意事项
数据存储:
- busuanzi 数据存储在第三方服务器(busuanzi.ibruce.info)
- 无法手动修改访问数据
- 如需完全控制数据,建议使用自建统计服务(如 Umami)
性能优化:
- 使用
async异步加载脚本,不阻塞页面渲染 - 格式化脚本放在页面底部执行
- 使用轮询方式检查数据更新,避免无限循环
- 使用
显示优化:
- 初始值 0 时隐藏,避免闪烁
- 列表页通过 CSS 强制隐藏访问量
- 防止重复格式化,避免显示异常值(如 33360.3k)
兼容性:
- busuanzi 服务依赖第三方,可能出现不稳定情况
- 建议定期检查统计是否正常
- 如遇异常数据,可联系 busuanzi 作者或考虑切换统计服务
文件修改清单
修改的文件
themes/hugo-theme-stack/hugo.yaml- 在
params.footer中添加showStats和showRuntime配置开关 - 添加
params.busuanzi配置
- 在
themes/hugo-theme-stack/layouts/partials/footer/footer.html- 添加
showRuntime运行时间统计功能 - 添加
showStats文章统计功能 - 添加 busuanzi 站点统计显示
- 添加
themes/hugo-theme-stack/layouts/partials/article/components/details.html- 添加 busuanzi 文章访问量显示
layouts/partials/google_analytics.html(新建)- 加载 busuanzi 脚本
themes/hugo-theme-stack/layouts/partials/footer/components/script.html- 添加 busuanzi 数字格式化脚本
themes/hugo-theme-stack/assets/scss/partials/article.scss- 添加 CSS 规则,隐藏列表页中的访问量
测试验证
页脚统计功能
-
showStats开关正确控制文章统计显示 -
showRuntime开关正确控制运行时间统计显示 - 文章统计显示正确的文章数和字数(万、千格式)
- 运行时间统计从第一篇文章日期开始计算
- 运行时间格式正确(x 年 x 月 x 天)
- 没有文章时不显示运行时间统计
busuanzi 访问量统计
- 站点统计正确显示总访问量和总访客数
- 文章详情页正确显示文章阅读量
- 列表页不显示访问量
- 数字大于 1000 时正确转换为 k 格式
- 初始值 0 时隐藏,数据加载后显示
- 不会出现重复格式化问题
总结
通过以上集成,实现了:
- 页脚统计功能:显示文章统计和运行时间,增强网站信息展示
- busuanzi 访问量统计:集成第三方统计服务,显示站点和文章的访问数据
- 数字格式化:自动将大数字转换为易读的 k 格式
- 显示优化:避免闪烁和重复格式化问题,提升用户体验
这些功能都遵循了主题的设计规范,使用主题提供的 CSS 变量和响应式断点,确保样式的一致性和可维护性。