Hexo 添加不蒜子和 LeanCloud 统计

前置提示:Hexo 版本为 3.9.0,NexT 版本为 5.1.1(不是最新版)

不蒜子 统计站点的总访问量,即统计浏览了多少次;有多少人访问,在 footer 显示。

LeanCloud 统计单篇博文的阅读量,即统计单篇博文的阅读量是多少。

不蒜子配置使用

下面教程针对 NexT 主题设置。

找到站点的 themes/next/layout/_partials 目录下的 footer.swig 文件。插入代码如下。

{% if theme.copyright %}
<div class="powered-by">
{{ __('footer.powered', '<a class="theme-link" href="https://hexo.io">Hexo</a>') }}
</div>

<div class="theme-info">
{{ __('footer.theme') }} -
<a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
NexT.{{ theme.scheme }}
</a>
</div>

# 此位置插入以下代码
<div>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

本站总访问量 <span id="busuanzi_value_site_pv"></span> 次 & nbsp&nbsp&nbsp
本站访客数 <span id="busuanzi_value_site_uv"></span > 人次
</div>

{% endif %}

LeanCloud 配置使用

不蒜子也可以统计单篇博文的阅读量,但是有两个缺点:

  1. 在首页不能查看博文的阅读量。
  2. 不能管理相关博文的阅读量(我认为是缺点)。

我使用 LeanCloud。原来使用 leancloud.cn,但因为 LeanCloud 的 lncld.net 域名 2022 年 1 月 27 日 被禁,导致其 SDK 无法直接使用,需要绑定自定义域名,而自定义域名国内又需要备案,所以转而使用国际版 leancloud.app。因为 NexT 版本较老,所以需要修改 NexT 源文件。

1、创建应用、新建 Class

leancloud.app注册登录后,进入控制台,创建一个新应用,如 Hexo。点击 存储,按下图标记新建一个 Class,Class 名称必须为 Counter(NexT 代码写死为了 Counter)。

获取应用凭证

按下图标记复制 App IDApp KeyREST API 服务器地址

复制后,更改 主题配置文件leancloud_visitors: 。注意将 enable 设为 true

# Show number of visitors to each article.
# You can visit https://leancloud.cn get AppID and AppKey.
leancloud_visitors:
enable: true
app_id: #your App ID
app_key: #your App Key
server_url: #your 上图的 REST API 服务器地址。没有这一行的话新增

优化 NexT 的 LeanCloud 脚本

如果你 NexT 中有 lean-analytics.swigthemes/next/layout/_third-party/analytics/lean-analytics.swig)这个文件,需将其修改为以下内容:

{%- if theme.leancloud_visitors.enable and not theme.valine.visitor %}  
<script{{ pjax }}>  
(function() {
  function leancloudSelector(url) {
    url = encodeURI(url);
    return document.getElementById(url).querySelector('.leancloud-visitors-count');
  }

  function addCount(Counter) {
    var visitors = document.querySelector('.leancloud_visitors');
    var url = decodeURI(visitors.id);
    var title = visitors.dataset.flagTitle;

    Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({ url })))
      .then(response => response.json())
      .then(({ results }) => {
        if (results.length > 0) {
          var counter = results[0];
          leancloudSelector(url).innerText = counter.time + 1;
          Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
            .catch(error => {
              console.error('Failed to save visitor count', error);
            });
        } else {
          {%- if theme.leancloud_visitors.security %}
            leancloudSelector(url).innerText = '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', { title, url, time: 1 })
              .then(response => response.json())
              .then(() => {
                leancloudSelector(url).innerText = 1;
              })
              .catch(error => {
                console.error('Failed to create', error);
              });
          {%- endif %}
        }
      })
      .catch(error => {
        console.error('LeanCloud Counter Error', error);
      });
  }

  function showTime(Counter) {
    var visitors = document.querySelectorAll('.leancloud_visitors');
    var entries = [...visitors].map(element => {
      return decodeURI(element.id);
    });

    Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({ url: { '$in': entries } })))
      .then(response => response.json())
      .then(({ results }) => {
        for (let url of entries) {
          let target = results.find(item => item.url === url);
          leancloudSelector(url).innerText = target ? target.time : 0;
        }
      })
      .catch(error => {
        console.error('LeanCloud Counter Error', error);
      });
  }

  let { app_id, app_key, server_url } = {{ theme.leancloud_visitors | json }};
  function fetchData(api_server) {
    var Counter = (method, url, data) => {
      return fetch(`${api_server}/1.1${url}`, {
        method,
        headers: {
          'X-LC-Id'     : app_id,
          'X-LC-Key'   : app_key,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(data)
      });
    };
    if ($('.leancloud_visitors').length == 1) {
      addCount(Counter);
    } else if ($('.post-title-link').length > 1) {
      showTime(Counter);
    }
  }

  let api_server = app_id.slice(-9) !== '-MdYXbMMI' ? server_url : `https://${app_id.slice(0, 8).toLowerCase()}.api.lncldglobal.com`;

  if (api_server) {
    fetchData(api_server);
  } else {
    fetch('https://app-router.leancloud.cn/2/route?appId=' + app_id)
      .then(response => response.json())
      .then(({ api_server }) => {
        fetchData('https://' + api_server);
      });
  }
})();
</script>

{%- endif %}

我的 NexT 版本是 5.1.1,原来默认使用 https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js ,这个链接已不能使用,我想找到一个备份,但没有找到。

我就切换策略,找其 NexT 新版本的 LeanCloud 脚本代码,将 lean-analytics.swig 替换,最后去除了 CONFIG 变量,就可以正常使用了。

$ hexo clean
$ hexo g
$ hexo d

参考资料