2022-12-02 更新
根据评论区小伙伴 @MareDevi 的介绍,成功解决了文章浏览量显示的问题,撒花!🌸
想来想去,很多问题还是没有解决,主要还是 Waline
与博客主题不完全兼容,加上自己对前端也不是很了解,最后还是改了回去。真是太折腾了。流石程序员。
# 前言
由于 Valine
评论系统的通知问题以及其他原因,考虑更换 Waline
作为新的评论系统,但是原来的 Shoka
主题使用的是作者修改后的 MiniValine
系统,在修改上碰到了很大的麻烦,最后只能忍痛割爱更换了现在的 butterfly
主题。这次更换也是对博客进行了一个大刀阔斧的修改,但是也摆脱了 Valine
系统这个累赘。原来经常有评论无法及时提醒,而我自己有时候又不会经常上网站查看,因此有的消息过了很久才能发现。最后还是下定决心进行迁移。
经过查找,发现了一个小姐姐提供的修改方法[1],在 Shoka
中能够引入 Waline
。最后还是保留了 Shoka
主题,然后将评论系统换成了 Waline
的系统,虽然还有一些兼容性上的问题,但总归还算保住了现在这个好看的主题。有些小问题折腾了几天也没能完全解决,姑且就到此为止吧。关于遇到的问题,在文章最后一小节有补充。
# 域名注册
这次顺便更换了一个自己的域名。经过一番搜索后选择了 Dynadot 域名商,域名就是现在的 linn-ylz.com
。依照教程[2]购买域名,全部完成之后,使用 Cloudflare
的 DNS
服务,参考另一个教程[3]。
以上的步骤按照教程基本能够比较轻松地完成,不多赘述。
# 自定义域名
在 Vercel
中设置自定义域名需要和 Cloudflare
的配置相匹配,具体可以参考这篇教程。需要注意,在 Cloudflare
中,需要将 SSL/TLS
的加密模式设置为完全(Full),否则可能会遇到 “重定向过多” 的错误而无法访问。
# 更换 Waline
按照 Waline
的教程进行配置。
# LeanCloud 设置
因为之前已经注册配置过 LeanCloud
了,所以这里不再赘述。可以参考之前的文章Shoka 评论推送功能实现。
# Vercel 配置
注册 Vercel
完成之后,按照 Waline
的官方教程进行配置。我在这里碰到了一点问题,从 Waline
的入口进入 Vercel
之后,在选择 GitHub
仓库的时无法填写表格,因此无法直接进行 deploy。但是直接选择自己的仓库却又可以。最后只能采用曲线救国的方法,自己 Fork 了仓库,然后再从自己的仓库中进行选择。然而直接 deploy 仓库会报错 This Serverless Function has crashed
,据官方说法,只需要复制 example
文件夹下的内容即可[4]。
在 Vercel
的 Settings
中,选择 Environment Variables
添加环境变量,主要是 LEAN_ID
, LEAN_KEY
, LEAN_MASTER_KEY
三个值。
如果是使用的国内版的 LeanCloud
,还需要额外设置 LEAN_SERVER
变量。
# 添加自定义域名
参照 Waline
教程中的内容,在 Settings
中选择 Domain
进入域名配置页。教程的说明进行配置。
关于在域名服务器商处添加新的 CNAME
解析记录这一条,由于我是在 Cloudflare
注册的 DNS
服务,因此需要在其中进行配置。
Type | Name | Value |
---|---|---|
CNAME | example | cname.vercel-dns.com |
Type | Name | Value |
---|---|---|
CNAME | example | cname.vercel-dns.com |
按我自己的例子,我的域名是 linn-ylz.com
,我选择的用于 Waline
的域名是 comments.linn-ylz.com
,那么在 Cloudflare
配置中添加 CNAME
配置,名称输入 comments
,对应的值为 cname.vercel-dns.com
。
上述配置完成之后可以从 Vercel
中打开网页进行评论测试。
# 邮件通知配置
这一部分主要参考 Waline
中的评论通知教程内容。我选择的是其中的邮件通知服务。教程中列举了以下必须配置的内容:
SMTP_SERVICE
: SMTP 邮件发送服务提供商。SMTP_USER
: SMTP 邮件发送服务的用户名,一般为登录邮箱。SMTP_PASS
: SMTP 邮件发送服务的密码,一般为邮箱登录密码,部分邮箱 (例如 163) 是单独的 SMTP 密码。SITE_NAME
: 网站名称,用于在消息中显示。SITE_URL
: 网站地址,用于在消息中显示。AUTHOR_EMAIL
: 博主邮箱,用来接收新评论通知。如果是博主发布的评论则不进行提醒通知。
以上变量均在 Vercel
中的环境变量设置中添加。由于官方文档惜字如金,所以这里再详细说一下配置的细节。
SMTP_SERVICE
、 SMTP_USER
、 SMTP_PASS
这三项内容是对应发送通知邮件的邮箱。比如我有两个邮箱,一个是 QQ 邮箱,另一个是 Outlook 邮箱,我选择用 QQ 邮箱发送消息到我的 Outlook 邮箱,通知有评论相关的内容到达。那么以上三项内容便需要填写 QQ 邮箱相关的信息。比如 QQ 邮箱的 SMTP_SERVICE
是 QQ
, SMTP_USER
即对应 QQ 邮箱,如 [email protected]
。而 SMTP_PASS
并不是 QQ 邮箱的密码,需要在 QQ 邮箱的 设置
中,找到 账户
选项卡,在 POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务
一栏有一个提示,最后有一个生成授权码的可点击链接,点击它之后,会要求你向某个号码发送一条指定内容的短信,发送完成之后会弹窗提示你一个授权码,这个授权码即填写到 SMTP_PASS
中的内容。
SITE_NAME
是消息中显示的网站名称, SITE_URL
则是网站的地址。注意这里填写的地址要包含前面的协议部分,以我自己为例就是 https://linn-ylz.com
。[5]
AUTHOR_EMAIL
就是用于接收评论通知的邮箱。
以上内容如果均配置正确,那么应该能够正常接收通知了。
# 修复 LeanCloud 数据库格式问题
尽管 Waline
也支持 LeanCloud
,但是在读取其中的内容时,因为数据库表格键值的不匹配会在显示上出现一些问题,这点可能和我之前使用的是 MiniValine
有关。
# 阅读量
首先是阅读量的问题,在 LeanCloud
原来的内容中,存储了之前的网页的访问数量。但是转到 Waline
之后数值却从 开始计算了。在 LeanCloud
后台,也发现和原来的文章不算同一个数据列。经过一番排查没有找到很好的解决办法,因此只能把之前的计数值复制到新的数据项之中,因为文章数量不多,操作起来倒也没费太多时间。
# 评论
在 Vercel
搭建好之后,进入 Waline
的管理平台,发现虽然评论能够正常读取,但是评论的时间显示却存在问题,经排查, Waline
使用的是 insertedAt
列的数据作为评论的发表时间,而之前的数据则是直接使用的 createdAt
列的数据,因此 Waline
读取不到之前评论的发表时间,这里把 createdAt
列的内容复制到 insertedAt
列之后可以正常显示时间了。
另一个问题是在文章的底部没有显示对应的评论,经排查,是因为之前的评论系统使用的路径是 A/B/
这样的格式,而 Waline
使用的是 /A/B
的格式,相差了一个 /
符号,修正过后,评论能够在文章底部正常显示。
# 网站访问量
网站的访客数量统计使用的是 “不蒜子”,但是其无法进行初始化,因此已经搭建好一段时间的网站的数值便不准确,这里参考这篇文章的办法,在主题文件中修改 card_webinfo.pug
文件,在其中添加以下内容:
script. | |
function checkPv(){ | |
var init_pv = parseInt(!{theme.busuanzi.init_pv}) | |
var pv = document.getElementById("busuanzi_value_site_pv") | |
if (pv.innerText === ''){ | |
setTimeout(checkPv, 100) | |
} else { | |
pv.innerText = parseInt(pv.innerText) + init_pv | |
} | |
} | |
script checkPv() | |
script. | |
function checkUv(){ | |
var init_uv = parseInt(!{theme.busuanzi.init_uv}) | |
var uv = document.getElementById("busuanzi_value_site_uv") | |
if (uv.innerText === ''){ | |
setTimeout(checkUv, 100) | |
}else{ | |
uv.innerText = parseInt(uv.innerText) + init_uv | |
} | |
} | |
script checkUv() |
# 在 Shoka 中使用 Waline
如文章开头所述,使用了一个小姐姐提供的方法[1:1],成功将评论系统更换为了 Waline
。虽然如此,但是还存在一些问题。
首先是和 MiniValine
的冲突问题,原来博客中的最近评论和文章浏览量统计是通过 MiniValine
的功能实现的,更换为 Waline
之后便失效了。虽然 Waline
也有提供这些功能,但是由于本人对于前端实在是苦手,因此最后也只是解决了最近评论的问题。文章浏览量统计在很多时候还是不能正常显示,只有通过刷新网页才能够正常显示,最后还是妥协成现在这个状况了。
# 最近评论问题
对于最近评论,我采用的办法是在网页 DOM 结构树生成完成之后,通过 Waline
的 API 接口进行查询,然后输出到网页中。这里的代码参考的是刚才提到的小姐姐的 GitHub
中的相关文件[6]。
const getRecentComments = function () { | |
console.log("getRecentComments triggered.") | |
if (CONFIG.waline.serverURL) { | |
var t = document.querySelector(".waline-recent-comments"); | |
function renderTime(date) { | |
let myDate = new Date(date).toJSON(); | |
return new Date(+new Date(myDate) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '') | |
} | |
function formatTime(time) { | |
let d = Math.floor(time / (1000 * 60 * 60 * 24)); | |
let h = Math.floor(time / (1000 * 60 * 60) % 24); | |
let m = Math.floor(time / (1000 * 60) % 60); | |
let s = Math.floor(time / 1000 % 60); | |
if (d > 0) { | |
return d + ' 天前' | |
} else if (h > 0) { | |
return h + ' 小时前' | |
} else if (m > 0) { | |
return m + ' 分钟前' | |
} else if (s > 0) { | |
return s + ' 秒钟前' | |
} | |
} | |
let str = ' @ ' | |
let reg = /<.*?>/ig; | |
let date = new Date(); | |
let url = CONFIG.waline.serverURL; | |
let count = 10; | |
var t = document.querySelector(".waline-recent-comments"); | |
if (t && !t.classList.contains("loaded")) { | |
console.log("load recent comments"); | |
fetch(url+'/comment?type=recent&count='+count) | |
.then(response => response.json()) | |
.then(data => { | |
let arr = data.filter(item => item.pid !== undefined); | |
let i = arr.length; | |
console.log("total " + i + " comments"); | |
for (var r = "", o = 0; o < i; o++) { | |
let comment = arr[o].comment.replace(reg, ''); | |
let gap = formatTime(date - new Date(renderTime(arr[o].createdAt))) | |
r += `<li class="item"><a href="${arr[o].url + '#' + arr[o].objectId}"> | |
<span class="breadcrumb">${arr[o].nick + str + gap}</span> | |
<span>${comment}</span></a></li>`; | |
t.innerHTML = r; | |
t.classList.add("loaded"); | |
// e.config.pjax && e.config.pjax.refresh(t) | |
} | |
}).catch(console.error) | |
} | |
} | |
} |
上述内容我添加在 source/js/_app/pjax.js
文件中,直接添加在最底部即可。上述函数添加后,再添加一个事件监听器:
window.addEventListener('DOMContentLoaded', getRecentComments); |
该监听器表示在 DOM 资源生成完毕之后,执行该函数进行查询。
# 文章浏览量统计
文章浏览量统计和最近评论的解决思路类似,也是在 DOM 结构树生成完毕之后,进行查询。
const getPageView = function () { | |
console.log("getPageView triggered."); | |
if (CONFIG.waline.serverURL) { | |
var t = document.querySelector(".leancloud-visitors-count"); | |
let path = window.location.pathname; | |
let url = CONFIG.waline.serverURL; | |
if (t) { | |
console.log("Load page views"); | |
console.log("Current page path: " + path); | |
let https = url+'/article?path='+path; | |
fetch(https) | |
.then(response => response.json()) | |
.then(data => { | |
console.log("Pageview: " + data); | |
t.innerHTML = data; | |
}).catch(console.error); | |
} | |
} | |
} | |
window.addEventListener('DOMContentLoaded', getPageView); |
除此之外,还需要修改 layout/_partials/post/footer.njk
这一文件中的内容。首先把 if theme.valine.appId and theme.valine.appKey and theme.valine.visitor
这一语句修改成 if theme.waline.serverURL
,否则在没有 Valine
配置的情况下,文章浏览量的元素不会显示。然后把 <span id="{{ page.path | replace('index.html', '') }}"...">
这个标签中的内容修改掉,比如我修改成了 <span class="item">
。这里之所以把 <span>
标签中的内容修改掉是因为我发现如果保留该标签,该数值一直是 ,应该是会被某个脚本执行的内容覆盖掉。具体原理还不明确。
但是这个方法存在的问题是,除非刷新网页,否则浏览数据不会正常显示。
尽管花了很多时间尝试别的方法,但是最后还是没有彻底解决。如果有哪位前端大佬能够不吝赐教,感激不尽。
# 评论系统样式问题
由于 Waline
系统的默认样式和 Shoka
不是非常搭配,因此仍然参考小姐姐的教程[1:2]进行了配置,但是发现并没有生效。经过排查是因为原来主题中存在的 MiniValine
相关的样式覆盖了配置的样式。最好把相关的 MiniValine
的内容全部注释掉。
# 终
花了几天总算是把博客主题折腾好了。虽然花了不少功夫,还额外给网页增加了几十次浏览量。 还有些问题没有完全解决,但是能够保住这个主题还是很高兴的。只要能保住太原,他要多少我给多少!