NexT主题之LeanCloud切换国际版

LeanCloud 分为国内版和国际版, 虽然说功能都是大同小异的,不过对于实名认证这件事做法却大不一样。国内版需要身份证实名,并且需要支付宝或银行卡进行辅助验证。而国际版只需验证邮箱和手机号即可使用。8月5号消息:国内版还需要绑定自己的域名,总之限制多多,所以就有很多人转向了国际版。

PS:有关 LeanCloud 实现文章阅读量、文章排行榜、Valine 评论功能的。可参考这篇文章:

NexT 文章阅读量排行(热榜)功能

正文

在讲解切换的步骤之前,说一下我本地环境: Hexo: 3.9.0   NexT:5.1.4

使用hexo v命令可查看当前hexo版本。主题配置文件中的version字段即所使用的主题版本

Tips:若LeanCloud中没有数据,以下导出导入步骤可略过!

数据导出

由于之前使用 Leancloud 中国版一段时间,已经存了部分数据了,所以需要导出,然后倒入国际版 Leancloud 中去。

导出步骤如下图所示:

导出步骤图

“限定导出数据起止时间”和“限定 class” 可以不选,则导出全部数据。我这只有三个 class 有数据,时间不长,所以按需导出了。

然后你绑定的邮箱账号就会收到邮件,点击给出的地址下载即可,默认是 tar.gz 文件,解压后得到一个个的 json 文件。

导出需要注意右上角的提示:“You can’t export data after 12:00 pm.”

数据导入

登录leancloud国际版,进入控制台,操作步骤如下:

n1QTJg.png

点击2然后“数据导入”:

填写要导入的 “Class 名称”,然后“选择数据文件”,点击“导入”,等待导入完成。其它的 Class 重复同样的操作即可。

部分Class介绍:

_User:用户数据表, _若此表共享,不同应用之间可打通帐户,实现相互注册和登录。
Comment:Valine 评论系统所保存的用户评论信息,包括昵称、邮箱、评论内容等信息。
Counter:保存单篇文章阅读量,基于此可实现排行榜功能。

代码整合问题

网上也有 leancloud 切换国际版的文章,做法是升级 next 版本(高版本修改过 leancloud 相关代码,不存在以上切换的问题)。

不过我没有这么做,本地next主题5.1.4,升级高版本会有太多不可预期的因素了,样式什么的肯定会错乱。已经在这个版本上改动太多东西了,不想再重新来过。。所以还是选择保守的做法。

先记录一下我切换过程中遇到的问题,然后贴上解决方案。(如果你 next 是 5.1.4 这个版本,你可能也会遇到这些问题)

问题 1

不是要切换 LC 嘛,直接找到配置的地方,将主题配置文件中的 leancloud_visitors 下的 appidappkey 替换成国际版中新建的应用 Key,做完这个 hexo 三连,报错了:

1
{"code":403,"error":"Access denied by api domain white list.The request origin header is 'null'."}

报错的请求的 URL 为:https://us.leancloud.cn/1.1/classes/Comment?redirectByAPI=cn

官方给的解释:

1
2
3
4
5
6
403
当应用在控制台中的相关服务选项未打开,如 Class 关闭了权限,或是 User 缺失了 session 信息等情况下,云端会统一地返回 403 错误码及不同的错误信息,代表当前请求因权限不够而被拒。例如:
信息 - Forbidden to read/write by class permissions
含义 - 操作被禁止,因为 Class 表没有打开「读」或者「写」的权限。进入 控制台 > 存储,点击相应的 Class,从右侧选择 其他 下拉菜单,进入 权限管理 来调整。
信息 - The user cannot be altered by a client without the session.
含义 - 用户没有登录,无法修改用户信息。

参考这里:

错误码详解 - LeanCloud 文档

Next 官方也有类似是 PR 修复:不过是解决和 Valine 冲突的,好像并不能解决我们现在的问题。

网上有贴了解决方案:建议更新av-min.js

找到本地的 lean-analytics.swig,位于 next/layout/_third-party/analytics/ 目录下,找到相关的 js 引用,5.1.4 版本的 next 引用的如下:

1
<script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>

版本还是很早前的,试着替换成

1
<script src="https://cdn1.lncld.net/static/js/3.10.0/av-min.js"></script>

不过问题依然没有解决。。接着出现问题2

问题 2

替换应用的 js 版本后,出现了新的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
Uncaught TypeError: Cannot redefine property: applicationId
at Function.defineProperty (<anonymous>)
at init.js?ddd7:165 Uncaught TypeError: Cannot redefine property: applicationId
at Function.defineProperty (<anonymous>)
at init.js?ddd7:165
at Array.forEach (<anonymous>)
at Object.<anonymous> (init.js?ddd7:174)
at e (bootstrap bacf8240e97c4b30b3d3?b629:19)
at Object.<anonymous> (index.js?9552:19)
at e (bootstrap bacf8240e97c4b30b3d3?b629:19)
at bootstrap bacf8240e97c4b30b3d3?b629:65
at bootstrap bacf8240e97c4b30b3d3?b629:65
at universalModuleDefinition?5ca6:9

多方查看无果后,心想应该是替换了新的 js 与现有主题已有的代码逻辑不符。因为主题中在 lean-analytics.swig 已经给我们集成好了相关的 leancloud 代码。

查看 github 相关的 next 仓库发现,新版的 NexT v6 and v7 已和 v5.1.4 的剥离,老版本不再更新维护。

好奇的我比较了不同版本间的 lean-analytics.swig 文件差异,发现 v6.4.1 版本下的这个文件被修改过了,而且改动很大,改动维持到 v7.2.0 没怎么变。

v7.3.0 的时候又做过一些修改,主要是一些标签符号变动。看到这里,是不是突然间豁然开朗了~

lean-analytics.swig
post.swig

以上就是我在切换过程中遇到的俩问题。

解决方案

机智的我就把针对 lean-analytics.swig 变动的代码拷贝到了本地。

我是拷 v6.4.1 的,拷贝版本介于 v6.4.1 ~ v7.2.0 的都可以(拷贝 v7.3.0 时,代码运行起来后还是有点问题)。我对比了这好几个版本,发现没啥变动的,大家可以对比一下。

附上完整的拷贝代码:

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{% if theme.leancloud_visitors.enable and !theme.valine.visitor %}
{# custom analytics part create by xiamo; edited by LEAFERx #}
<script>
{% if page.layout === 'post' %}
function addCount(Counter) {
var $visitors = $('.leancloud_visitors');
var url = $visitors.attr('id').trim();
var title = $visitors.attr('data-flag-title').trim();

Counter('get', '/classes/Counter', { where: JSON.stringify({ url }) })
.done(function({ results }) {
if (results.length > 0) {
var counter = results[0];
{% if theme.leancloud_visitors.betterPerformance %}
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(counter.time + 1);
{% endif %}
Counter('put', '/classes/Counter/' + counter.objectId, JSON.stringify({ time: { '__op': 'Increment', 'amount': 1 } }))
{% if not theme.leancloud_visitors.betterPerformance %}
.done(function() {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(counter.time + 1);
})
{% endif %}
.fail(function ({ responseJSON }) {
console.log('Failed to save Visitor num, with error message: ' + responseJSON.error);
})
} else {
{% if theme.leancloud_visitors.security %}
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text('Counter not initialized! More info at console err msg.');
console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.');
{% else %}
Counter('post', '/classes/Counter', JSON.stringify({ title: title, url: url, time: 1 }))
.done(function() {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(1);
})
.fail(function() {
console.log('Failed to create');
});
{% endif %}
}
})
.fail(function ({ responseJSON }) {
console.log('LeanCloud Counter Error: ' + responseJSON.code + ' ' + responseJSON.error);
});
}
{% else %}
function showTime(Counter) {
var entries = [];
var $visitors = $('.leancloud_visitors');

$visitors.each(function() {
entries.push( $(this).attr('id').trim() );
});

Counter('get', '/classes/Counter', { where: JSON.stringify({ url: { '$in': entries } }) })
.done(function({ results }) {
var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

if (results.length === 0) {
$visitors.find(COUNT_CONTAINER_REF).text(0);
return;
}

for (var i = 0; i < results.length; i++) {
var item = results[i];
var url = item.url;
var time = item.time;
var element = document.getElementById(url);

$(element).find(COUNT_CONTAINER_REF).text(time);
}
for (var i = 0; i < entries.length; i++) {
var url = entries[i];
var element = document.getElementById(url);
var countSpan = $(element).find(COUNT_CONTAINER_REF);
if (countSpan.text() == '') {
countSpan.text(0);
}
}
})
.fail(function ({ responseJSON }) {
console.log('LeanCloud Counter Error: ' + responseJSON.code + ' ' + responseJSON.error);
});
}
{% endif %}

$(function() {
$.get('https://app-router.leancloud.cn/2/route?appId=' + '{{ theme.leancloud_visitors.app_id }}')
.done(function({ api_server }) {
var Counter = function(method, url, data) {
return $.ajax({
method: method,
url: 'https://' + api_server + '/1.1' + url,
headers: {
'X-LC-Id': '{{ theme.leancloud_visitors.app_id }}',
'X-LC-Key': '{{ theme.leancloud_visitors.app_key }}',
'Content-Type': 'application/json',
},
data: data
});
};
{% if page.layout === 'post' %}
const localhost = /http:\/\/(localhost|127.0.0.1|0.0.0.0)/;
if (localhost.test(document.URL)) return;
addCount(Counter);
{% else %}
if ($('.post-title-link').length >= 1) {
showTime(Counter);
}
{% endif %}
});
});
</script>

{% endif %}

接着 hexo 三连 后,访问首页已经有效果了,每篇文章的阅读数都有了,而且排行榜的数据也正常显示。接着点开一篇文章,阅读数没有显示:

刚开始以为是浏览器缓存什么的,然而刷新 N 次、重启 N 次还是无济于事,内心是崩溃的。😭

作为一名合格Java 大(cai)师(niao),怎么会没辙呢。。代码读起来~

终于,在刚才新改的 lean-analytics.swig 文件中,找到如下代码:

1
2
3
4
5
6
7
8
9
{% if page.layout === 'post' %}
const localhost = /http:\/\/(localhost|127.0.0.1|0.0.0.0)/;
if (localhost.test(document.URL)) return;
addCount(Counter);
{% else %}
if ($('.post-title-link').length >= 1) {
showTime(Counter);
}
{% endif %}

第二个 if 判断,当是 localhost 的时候,给 return 掉了。

代码中的 addCount 是增加文章阅读数的方法。也是阅读数赋值的地方。前面 return 了,这里当然不能执行了,所以本地阅读数就显示不出来了。。

这代码的目的,我想应该是为了忽略本地文章调试时所增加的阅读量而做的。如果要本地也开启文章阅读数,不考虑阅读数量因此增加的话,注释这行代码即可

注意一下第一个 if 判断。有时候你在新建文章的时候,文章开头的 formatter 可能是 layout: hexo,这时候文章阅读数也是不会显示。。我就遇到这种情况,其他文章都正常,就某两篇有问题,查来查去发现是这个 layout 的事。。。

另外

1、Valine 评论系统切换,只要在此基础上直接替换其所使用的 appidappkey 即可。

2、排行榜(热榜)功能,只需要修改其对应的 index.md 文件(之前引入的 js 已是新版):

1
2
<script src="https://cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script>AV.initialize("你的国际版leancloud App ID", "你的国际版leancloud Key");</script>

接着 hexo 三连,效果已经有了,部署正式环境,文章阅读数、排行榜、Valine 都正常,至此切换 LeanCloud 国际版已完成。

可选配置:hexo-leancloud-counter-security 插件

背景:NexT 使用的 Leancloud 访客统计插件存在重大安全漏洞,拥有不良企图的人利用该漏洞可随意更改访客数量或一定程度上增删数据库记录。

该插件主要是为了修复 LeanCloud 统计插件安全漏洞

hexo-leancloud-counter-security

Leancloud访客统计插件重大安全漏洞修复指南

写在最后

总结一下,关于 Leancloud 切换国际版,针对 NexT v5.1.4 版本,其实就是升级了其依赖的 leancloud 的 JS 版本,解决了低版本下代码不兼容的问题。

版本参见:

LeanCloud.releases

部署后,还发现一个 suprise:手机端热榜文章阅读数都能正常显示了。

因为我做了一些手机端样式适配(可参考我的这篇文章),发现这些功能并不正常,不知道是不是 Leancloud 这样在手机端访问的一些问题。

点击查看

本文标题:NexT主题之LeanCloud切换国际版

文章作者:北宸

发布时间:2019年08月29日 - 18:25:08

最后更新:2023年08月19日 - 13:26:00

原始链接:https://www.liaofuzhan.com/posts/554801533.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------
🌞