抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

volantis主题对于artalk评论系统适配较为完善,可实现开箱即用的文章评论与基础浏览量统计功能。但如需扩展更多统计维度,需手动配置实现。虽然主题自带了busuanzi和leancloud统计,但是busuanzi加载真的太太太慢了,而且统计的很抽象,leancloud感觉又有点复杂。折腾artalk的过程中发现也能做到很多统计,搞一搞试试。

一、前言

统计功能的实现依赖于artalk评论组件的部署,对于首页、归档页等未默认配置评论功能的页面,需先添加评论组件并隐藏显示(仅用于统计数据收集)。例如以首页页面为例:

击查看代码
volantis/layout/layout.ejs
1
2
3
4
5
6
7
8
9
10
11
12
    <div id="safearea">
<div class="body-wrapper">
<%- body %>
<%- partial('_plugins/pjax/pdata') %>
</div>
<%- partial('_partial/footer', null, {cache: !config.relative_link}) %>
<a id="s-top" class="fa-solid fa-arrow-up fa-fw" href="/" onclick="return false;" title="top"></a>
</div>
+ <%# 首页添加artalk评论用于统计浏览量 %>
+ <div style="display: none">
+ <%- partial('/_plugins/comments/index') %>
+ </div>

此外,所需样式代码引入可以直接写在blog/source/_volantis/bodyEnd.ejs文件中,确保统计组件的正常渲染。。

二、统计全站浏览量

1、收集目标页面 URL字段

为确保统计覆盖全站有效页面,需收集以下几类页面的 URL 并统一处理:

  1. 首页、归档页:直接手动添加;
  2. 所有文章页面:通过 Hexo 接口批量获取并处理链接格式;
  3. 自定义页面:从主题配置文件中提取链接(导航栏处)。
点击查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%
// 保存网站中所有包含artalk评论的页面URL字段
const allPostUrls = [];
// 一、添加首页、归档页
allPostUrls.push("/");
allPostUrls.push("/archives/");
// 二、获取所有文章(归档页)的url
site.posts.each(function (post) {
if (post.archive === undefined || post.archive === true) {
// 1. 生成原始URL(带.html后缀)
let postUrl = url_for(post.link || post.path);
// 2. 去掉尾部的.html后缀(使用replace替换)
postUrl = postUrl.replace(/\.html$/, '');
// 3. 存入数组
allPostUrls.push(postUrl);
}
});
// 三、获取导航栏所有自定义页面的url
const list_menu = theme.navbar.menu
list_menu.forEach(item => {
if (item.rows && Array.isArray(item.rows)) {
item.rows.forEach(row => {
if (row.url) {
allPostUrls.push(row.url);
}
});
}
});
%>

注意:若未使用 permalink 优化文章链接,需在 “获取所有文章的 url” 步骤中调整代码逻辑以适配实际链接格式

最终收集的 url格式示例如下:

1
2
3
allPostUrls=[ '/','/archives/',
'/post/xxx/', '/post/xxx/', '/post/xxx/',
'/about/', '/friends/', '/comment/', ]

2、调用 API 获取并展示浏览量

①首先在需要展示数据的页面中添加承载样式:

1
2
3
4
<div class="stat-item">
<div class="stat-number stat-visitor" data-count="">0</div>
<div class="stat-label">总阅读量</div>
</div>

②通过 artalk API 获取数据并渲染到页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%# 获取网站总浏览量 %>
const siteName = '<%- config.title %>';
const new_allPostUrls = <%- JSON.stringify(allPostUrls) %>;
var apiUrl = "<%- theme.comments.artalk.server %>/api/v2/stats/page_pv?page_keys=" + new_allPostUrls.join(",") + "&site_name=" + siteName;
fetch(apiUrl).then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
}).then(({data}) => {
const totalViews = Object.values(data).reduce((sum, views) => sum + views, 0);
const visitorEl = document.querySelector('.stat-visitor');
<%# visitorEl.dataset.count = totalViews; %>
visitorEl.innerHTML = totalViews;
}).catch(error => {
console.error('There was a problem with the fetch operation:', error);
});

三、统计总评论数

总评论数的统计逻辑与浏览量类似,直接调用 Artalk 提供的站点评论数 API 即可实现。

① 添加承载样式:

1
2
3
4
<div class="stat-item">
<div class="stat-number stat-comment" data-count="">0</div>
<div class="stat-label">总评论</div>
</div>

② 调用 API 获取并展示数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%# 获取网站总评论数 %>
const url = `<%- theme.comments.artalk.server %>/api/v2/stats/site_comment?site_name=${encodeURIComponent(siteName)}`;
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(({data}) => {
const commentEl = document.querySelector('.stat-comment');
<%# commentEl.dataset.count = JSON.stringify(data); %>
commentEl.innerHTML = JSON.stringify(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});

浏览量与评论数统计完整代码

将上述逻辑整合后,完整代码可放置于blog/source/_volantis/bodyEnd.ejs文件中:

点击查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<%
// 保存网站中所有包含artalk评论的页面URL
const allPostUrls = [];
// 一、添加首页、归档页
allPostUrls.push("/");
allPostUrls.push("/archives/");
// 二、获取所有文章(归档页)的url
site.posts.each(function (post) {
if (post.archive === undefined || post.archive === true) {
// 1. 生成原始URL(带.html后缀)
let postUrl = url_for(post.link || post.path);
// 2. 去掉尾部的.html后缀(使用replace替换)
postUrl = postUrl.replace(/\.html$/, '');
// 3. 存入数组
allPostUrls.push(postUrl);
}
});
// 三、获取导航栏所有自定义页面的url
const list_menu = theme.navbar.menu
list_menu.forEach(item => {
if (item.rows && Array.isArray(item.rows)) {
item.rows.forEach(row => {
if (row.url) {
allPostUrls.push(row.url);
}
});
}
});
// console.log(allPostUrls);
%>
<script>
<%# 获取网站总浏览量 %>
const siteName = '<%- config.title %>';
const new_allPostUrls = <%- JSON.stringify(allPostUrls) %>;
var apiUrl = "<%- theme.comments.artalk.server %>/api/v2/stats/page_pv?page_keys=" + new_allPostUrls.join(",") + "&site_name=" + siteName;
fetch(apiUrl).then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
}).then(({data}) => {
const totalViews = Object.values(data).reduce((sum, views) => sum + views, 0);
const visitorEl = document.querySelector('.stat-visitor');
<%# visitorEl.dataset.count = totalViews; %>
visitorEl.innerHTML = totalViews;

}).catch(error => {
console.error('There was a problem with the fetch operation:', error);
});

<%# 获取网站总评论数 %>
const url = `<%- theme.comments.artalk.server %>/api/v2/stats/site_comment?site_name=${encodeURIComponent(siteName)}`;
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(({data}) => {
const commentEl = document.querySelector('.stat-comment');
<%# commentEl.dataset.count = JSON.stringify(data); %>
commentEl.innerHTML = JSON.stringify(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
</script>

四、文章卡片统计数据展示

常规统计逻辑中,文章详情页的统计数据会在加载 Artalk 评论组件后自动获取(推测)。但首页文章卡片需单独配置,以实现列表页的数据展示。

①添加卡片统计样式

volantis主题的首页文章卡片代码渲染位置在volantis/layout/_partial/post.ejs文件中,在合适的位置添加浏览量与评论数的展示容器:

1
2
<span class="card_artalk_visitors" data-page-key="<%- url_for(post.link || post.path).replace(/\.html$/, '') %>">-</span><span>次浏览</span>
<span class="card_artalk_comment" data-page-key="<%- url_for(post.link || post.path).replace(/\.html$/, '') %>">-</span><span>条评论</span>
本站样式参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<%# 浏览量 %>
<div class="card-meta-counter">
<svg class="iconfont" aria-hidden="true">
<use xlink:href="#icon-redu"></use>
</svg>
<span class="card_artalk_visitors" data-page-key="<%- url_for(post.link || post.path).replace(/\.html$/, '') %>">-</span>
<span><%- theme.article.body.meta_library.counter.unit %></span>
</div>
<%# 评论数 %>
<div class="card-meta-comment">
<svg class="iconfont" aria-hidden="true">
<use xlink:href="#icon-woyaoliuyan"></use>
</svg>
<span class="card_artalk_comment" data-page-key="<%- url_for(post.link || post.path).replace(/\.html$/, '') %>">-</span>
<span><%- theme.article.body.meta_library.artalkcount.desc %></span>
</div>

②创建统计组件加载逻辑

volantis/layout/_partial/custom目录下创建custom_card.ejs文件,编写卡片统计数据的加载逻辑:

点击查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<script>
function card_load_artalk() {
volantis.css("<%- theme.comments.artalk.css %>");
volantis.js("<%- theme.comments.artalk.js %>")
.then(() => {
if (typeof Artalk === 'undefined') {
console.error('Artalk.js loaded but Artalk is not defined');
return;
}
return card_post_artalk();
})
.catch(err => {
console.error('Failed to load Artalk.js:', err);
});
}

function card_post_artalk() {
if (!window.Artalk) {
console.error("Artalk未加载,请检查脚本引入");
return;
}
Artalk.loadCountWidget({
server: '<%- theme.comments.artalk.server %>',
site: '<%- config.title %>',
pvEl: '.card_artalk_visitors',
countEl: '.card_artalk_comment',
statPageKeyAttr: 'data-page-key',
});
}
card_load_artalk();
</script>

注意:样式容器中的类名(如card_artalk_visitors)需与加载逻辑中的pvEl/countEl属性值保持一致,否则会导致数据无法正常渲染

③引入卡片统计组件

在首页文章列表的渲染文件中引入上述统计组件,确保数据在页面加载时同步加载:

volantis/layout/_partial/archive.ejs
1
2
3
4
5
6
7
8
<% if (site.posts && site.posts.length > 0) { %>
+ <%- partial('_partial/custom/custom_card') %>
<section class="post-list">
<%# page.prev 表示“上一页”,!page.prev 即当前是第一页 %>
<% if (!page.prev) { %>
<%# is_home() 是 Hexo 辅助函数,判断当前是否为首页 %>
<% if (is_home()) { %>
...

本站首页文章卡片样式参考:

总结

通过 Artalk 评论系统的内置 API,可高效实现全站浏览量、总评论数及文章卡片统计等功能,且数据加载速度取决于服务器部署位置,整体体验优于其他统计工具。另外Artalk的文档有点一言难尽,对小白来说太不友好了

灌水




豫ICP备20002107号-1

灌水