书接上文《使用memos搭建独立微博,self-host三件套齐全了

本文介绍:

1、Memos应用中添加Artalk评论
2、Typecho集成单页Memos并添加Artalk评论

Memos应用中添加Artalk评论

首先,你需要自建Artalk评论服务,可参考官网,此处不详细介绍了。

然后,在Memos的设置-系统中添加自定义样式和自定义脚本。

1、在自定义脚本中追加如下代码

将代码中Artalk相关的参数配置,替换为自己的。

// artalk comments
// css
document.head.innerHTML += '<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/artalk/2.5.4/Artalk.css" type="text/css"/>';
// js
function addArtalkJS() { 
    var memosArtalk = document.createElement("script");
    memosArtalk.src = `https://cdn.bootcdn.net/ajax/libs/artalk/2.5.4/Artalk.js`;
    var artakPos = document.getElementsByTagName("script")[0];
    artakPos.parentNode.insertBefore(memosArtalk, artakPos);
};
// div
function startArtalk() {
    start = setInterval(function(){
        var artalkDom = document.getElementById('Comments') || '';
        var memoAt = document.querySelector('.memo-wrapper') || ''; // 0.12.x的版本请将.memo-wrapper替换为.memo-container
        var memoLoading = document.querySelector('.action-button-container') || '';
        var memoLoadingA = document.querySelector('.action-button-container a') || '';
        if(window.location.href.replace(/^.*\/(m)\/.*$/,'$1') == "m" && memoLoadingA){
        memoLoading.innerHTML = "评论加载中……"
        }
        if(window.location.href.replace(/^.*\/(m)\/.*$/,'$1') == "m" && !artalkDom){
            addArtalkJS()
            if(memoAt){
                clearInterval(start)
                memoAt.insertAdjacentHTML('afterend', '<div id="Comments"></div>');
                setTimeout(function() {
                    Artalk.init({
                        el: '#Comments',
                        pageKey: location.pathname,
                        pageTitle: document.title,
                        server: 'https://artalk.skyue.com',
                        site: '拾月微博',
                        darkMode: 'auto'
                    });
                    Artalk.on('list-loaded', function() {
                        // console.log('评论加载完成');
                        memoLoading.innerHTML = ''
                        startArtalk();
                    });
                }, 1000);
            }
        }
        //console.log(window.location.href);
    }, 1000)
}
startArtalk();

2、在自定义样式中追加如下代码

a.time-text:after { content: ' 评论 💬 '; }
.atk-main-editor { margin-top: 20px; }

最终效果如下:

Typecho集成单页Memos并添加评论

先来欣赏下集成后效果,如下图所示。主要特点在于:评论框默认折叠,点击评论后评论框在当前页展开,无需跳转,类似微博。(点击这里线上体验)

网上有很多Memos单页应用示例代码,比如我用过一段时间木老师开发的版本

我的博客是Typecho搭建的,有服务端,这次我直接在主题(我用的默认主题)文件夹新建了一个memos.php的模板文件,并在服务端直接获取Memos数据并渲染,代码如下:

<?php $this->need('header.php'); ?>
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * Memos模板
 *
 * @package custom
 */
?>

<div class="col-mb-12 col-8" id="main" role="main">
<article class="post"><h2 class="post-title"></h2><article>
<?php
$url = 'https://memos.skyue.com/api/memo?creatorId=1&limit=300'; // 不限定内容类型
$ch = curl_init();  
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查 SSL 加密算法是否存在
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 6);
$response = curl_exec($ch);  
if($error=curl_error($ch)){  
    echo '微博加载错误';
}  
curl_close($ch);
$array_data = json_decode($response,true)['data'];
for($i=1; $i<count($array_data); $i++)
{
    $obj = $array_data[$i];
    // 下面这个if判断,是只展示最近30天的Memos
    if(time() - $obj['createdTs'] < 2592000){
        $memo_id = $obj['id'];
        $content = $obj['content'];
        $create_time = date('Y-m-d H:i:s',$obj['createdTs']);
        $resources = $obj['resourceList'];

        $content_tag = preg_replace_callback('/#([^\s\n]+)(?=\s|\n|$)/', function ($matches) {
            return '<span class="memo_tag">#' . $matches[1] . '</span>';
        }, $content);
        $content_html = Typecho_Widget::widget('Widget_Abstract_Contents')->markdown($content_tag); // 使用Typecho自带的Markdown解析器解析Memos

        $body_html = sprintf('
            <div class="memo-top-wrapper">拾月 · %s</div>
            <div class="memo-content-wrapper">%s</div>', $create_time, $content_html); 

        if($resources){
            $image_html = '<div class="resource-wrapper"><div class="images-wrapper"><div class="w-full memo-resource">';
            for($j=0; $j<count($resources); $j++){
                $image_html = $image_html.sprintf('<img src="%s" decoding="async" loading="lazy">', $resources[$j]['externalLink']);
            }
            echo '<article class="memo-wrapper">'.$body_html.$image_html.'</div></div></div><a style="cursor:pointer" onclick="loadArtalk(\''.$memo_id.'\')"><span id="btn_memo_'.$memo_id.'">评论</span>(<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>)</a><div style="display: none;" id="memo_'.$memo_id.'"></div></article>';
        }else{
            echo '<article class="memo-wrapper">'.$body_html.'<a style="cursor:pointer" onclick="loadArtalk(\''.$memo_id.'\')"><span id="btn_memo_'.$memo_id.'">评论</span>(<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>)</a><div style="display: none;" id="memo_'.$memo_id.'"></div></article>';
        }  // echo的html代码中,onclick属性调用下面的加载Artalk评论框代码,需要传memo_id参数
    }
}
?> <!-- Memos数据处理结束 -->

<div class="memo-bottom">更多内容前往<a href="https://memos.skyue.com" target="_blank">微博主站</a></div>

</div>

<!-- artalk文件 -->
<link href="https://npm.elemecdn.com/artalk@2.5.4/dist/Artalk.css" rel="stylesheet">
<script src="https://npm.elemecdn.com/artalk@2.5.4/dist/Artalk.js"></script>

<!-- 下面这段JS,在页面上点击评论按钮时触发,支持展开评论和收起评论 -->
<script>
function loadArtalk(memo_id){
    const commentDiv = document.getElementById('memo_'+memo_id);
    const commentBtn = document.getElementById('btn_memo_'+memo_id);
    if(commentDiv.style.display==='none'){
        commentDiv.style.display='block';
        commentBtn.innerHTML = '收起评论';
        new Artalk({
            el: '#memo_' + memo_id,  // 绑定元素的 Selector
            pageKey: '/m/'+memo_id,  // 固定链接 (留空自动获取)
            pageTitle: '拾月微博',    // 页面标题 (留空自动获取)
            server: 'https://artalk.skyue.com',  // 后端地址
            site: '拾月微博',         // 在后端中创建的站点名
        });
    }
    else{
        commentDiv.style.display='none';
        commentBtn.innerHTML = '评论';
    }
}
</script>

<!-- 这段js,在未展开评论时,就展示评论数量 -->
<script>
Artalk.loadCountWidget({
  server:  'https://artalk.skyue.com',
  site:    '拾月微博',
  pvEl:    '#ArtalkPV',
  countEl: '#ArtalkCount',
});
</script>

<?php $this->need('footer.php'); ?>

上面这段代码实现两个功能:

  1. 通过api抓取Memos数据并直接在服务端渲染。
  2. 提供了两段javascript代码,一个实现展示评论数,一个实现评论框的展开和收起。

如果是Typecho博客程序,大概率能使用上述代码,只根据自己的情况修改Memos api地址以及loadArtalk中serversite两个参数。

关于点击「评论」按钮的功能,关键是下面三处:

  1. 模板中每条memo下面预留一个div容器,容器idmemo_{memo_id},渲染后类似<div id="memo_1"></div>。其作用是在对应的memo下方加载评论框。
  2. 为「评论」按钮添加onclick属性,调用loadArtalk函数,调用时带上memo_id参数。这段js执行时,会寻找上面提到的容器,加载评论框,并获取对应Memo的评论进行展示。展开状态再点击,又会收起。
  3. 「评论」按钮括号内的评论数,是<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>起的作用。

下面是在主题文件夹style.css中追加的样式:

/* memo专用css */

article.memo-wrapper {
    padding: 15px;
    border: 1px solid darkgray;
    margin: 20px 0px;
}

.memo-content-wrapper {
    line-height: 1.6;
    font-size: 17px;
    word-wrap: break-word;
}

.memo-resource img {
    width: auto;
    max-width: 100%;
}

span.memo_tag {
    color: cornflowerblue;
}

.memo-bottom {
    margin: 50px 0px;
    text-align: center;
}

.memo-top-wrapper {
    color: gray;
}

以上,就这么点东西,周六晚上肝到凌晨4点,还好有ChatGPT。

另外,有些不完美的地方,比如:

  1. 现在图片是纵向平铺的,没有做九宫格缩略图。
  2. 没有详情页,从评论通知邮件打开Memos,还是memos.skyue.com站点。

留坑,有空再解决这两个问题,尤其是第2个,非常想在www.skyue.com主站实现memos详情页,技术上肯定可行,只是现在还不会。

🔔 Email RSS订阅本博客

已有 73 条评论

  1. 大家都开始添加评论功能,这手痒痒呀~

    1. 哈哈,搞起来。没有评论都不完整😂

  2. 不错不错!👍 教程拿走了。

    1. 看你的memos评论报错了,感觉是没有添加「可信域名」

  3. 看看https://github.com/kingwrcy/mblog-backend这个,多用户+评论的memos版!

    1. 上周也看到这个项目,且观察一段时间。
      我对多用户没诉求,不过是想要评论,但mblog的评论需要登录,我还是喜欢Typecho这种填个邮箱就能评论的,不用注册登录。

      1. 看来我也要学习一下,怎么整起来?不知有没具体教程,业务人士😂

        1. docker安装的话还是挺方便的。
          https://www.skyue.com/23021116.html
          我在上面这篇文章中简单介绍了docker安装memos的步骤。

  4. 这个不错,谢谢分享,参考一些代码,把我的 memos 也加上了评论。

    1. 在你的memos上尝试评论,返回如下错误:
      {"success":false,"msg":"无效的请求, 无法获取 origin","data":{}}

      1. 遇到安全域名跨域问题。谢谢提醒!

        Memos 应用上的评论代码有作业可以抄吗?

        1. js如下:

          // artalk comments
          // css
          document.head.innerHTML += '<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/artalk/2.5.4/Artalk.css" type="text/css"/>';
          // js
          function addArtalkJS() { 
              var memosArtalk = document.createElement("script");
              memosArtalk.src = `https://cdn.bootcdn.net/ajax/libs/artalk/2.5.4/Artalk.js`;
              var artakPos = document.getElementsByTagName("script")[0];
              artakPos.parentNode.insertBefore(memosArtalk, artakPos);
          };
          // div
          function startArtalk() {
              start = setInterval(function(){
                  var artalkDom = document.getElementById('Comments') || '';
                  var memoAt = document.querySelector('.memo-container') || '';
                  var memoLoading = document.querySelector('.action-button-container') || '';
                  var memoLoadingA = document.querySelector('.action-button-container a') || '';
                  if(window.location.href.replace(/^.*\/(m)\/.*$/,'$1') == "m" && memoLoadingA){
                  memoLoading.innerHTML = "评论加载中……"
                  }
                  if(window.location.href.replace(/^.*\/(m)\/.*$/,'$1') == "m" && !artalkDom){
                      addArtalkJS()
                      if(memoAt){
                          clearInterval(start)
                          memoAt.insertAdjacentHTML('afterend', '<div id="Comments"></div>');
                          setTimeout(function() {
                              Artalk.init({
                                  el: '#Comments',
                                  pageKey: location.pathname,
                                  pageTitle: document.title,
                                  server: 'https://artalk.skyue.com',
                                  site: '拾月微博',
                                  darkMode: 'auto'
                              });
                              Artalk.on('list-loaded', function() {
                                  // console.log('评论加载完成');
                                  memoLoading.innerHTML = ''
                                  startArtalk();
                              });
                          }, 1000);
                      }
                  }
                  //console.log(window.location.href);
              }, 1000)
          }
          startArtalk();

          css如下:

          a.time-text:after { content: ' 评论 💬 '; }
          .atk-main-editor { margin-top: 20px; }

          js有一些瑕疵,会导致memos设置中的系统设置界面排版出错,没去深究,但整体不影响使用。

          1. 把这部分:

            document.head.innerHTML += '<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/artalk/2.5.4/Artalk.css" type="text/css"/>';

            修改为:

            window.onload = function() {
              if (window.location.href.indexOf('/m/') !== -1) {
                document.head.innerHTML += '<link rel="stylesheet" href="https://your.domain.com/artalk/dist/ArtalkLite.css" type="text/css"/>';
              }
            };

            可以避免在后台加载 CSS 文件,只在 URL 中有 /m/ 路径时才加载。后台就不会乱了。

            1. 赞,把我的也修改了,现在舒服多了,哈哈。
              另:url已修改。

          2. Memos 0.13.0 版本好像不能用,改天再研究研究。

            1. TG 的 Memos 广场置顶消息:

              Memos 升级到最新的 1.3.0 版本,原来的 Twikoo 评论不能正常显示了。要把原来代码中的.memo-container 改为.memo-wrapper。

              应该是 html 元素的 class 属性值变了,试试。

          3. 谢谢!

  5. 看起来清爽多了,这个字体也挺好👍

    1. 霞鹜文楷,啥时候操作系统默认支持就好了,现在都是靠js和css,始终不太友好。

  6. 现在玩memos的人真多,我也跟疯了。。

    1. 确实好用,还有热心开发者做了ios和android app,非常方便。
      总的来讲,社区很活跃。

  7. 挺好的方案,听说官方也在做了

    1. 是的,也很期待官方评论功能。但看github上的信息,感觉是登录用户的评论,不知是否支持非登录用户。这个还挺重要的。

      1. QL QL

        Memos 今天发布的 0.16.0 版已经支持评论功能啦,不过确实是只有登录用户才能评论。官方的评论其实就是一条和被评论 Memo 链接起来的 Memo,感觉要支持游客评论的话其实也就是支持游客发表 Memo 了。

        1. 评论和Memos在数据库中可以存为两表,数据分开。
          现在的逻辑是,共用一个表,把评论当Memos。

          这个功能的设计,确实有些复杂,感觉怎么弄都有不合适的地方。不能苛求官方。

  8. 这个不错,还想着有空实现一下这个功能,正好可以参考一下。
    另外,在想有没有可能将一条笔记绑定一个空的评论,然后把这条评论的点赞(同意)按钮放到评论按钮旁边,这样可以利用Artalk简单实现点赞功能。😎

    1. 点赞功能这样操作过于track,直接给artalk提个FR比较合适,也确实挺好奇的,都加了pv功能,为啥不加个点赞交互,感觉差不多。

  9. 有评论的感觉就很棒,鲜枣折腾博客搞出问题先问GPT已经成习惯了,好用

    1. 我还没完全形成习惯,但折腾不动的时候会突然想到,为什么不问问ChatGPT。
      确实好用,大杀器。

  10. 这个想法很有趣 抄了抄了😂

    1. Typecho博客应该能直接食用

添加新评论