书接上文《使用 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 详情页,技术上肯定可行,只是现在还不会。

分类: 折腾 标签: Typecho, Memos, Artalk, 独立微博

已有 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 博客应该能直接食用

添加新评论

  • 😂
  • 😎
  • 😭
  • 😱
  • 😓
  • 💊
  • 💣
  • 👍
  • 🤝
  • 🙏
  • Emoji