书接上文《使用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, 独立微博

🔔 Email RSS订阅本博客

已有 73 条评论

  1. 厉害了,有好的创意和ChatGPT简直是如虎添翼~

    1. PHP和JS非常不熟,全靠ChatGPT。

      但发现ChatGPT解决通用型问题很强,但如果依赖特定API或特定的执行环境,就很难给出准确的代码了。

      比如一直想让ChatGPT写一个Obsidian插件,实现发布内容到Typecho博客,就搞不定。

      1. 那是ChatGPT没联网的原因,数据库太陈旧,好多最新的技术代码它不会,等到联网就好多了吧?

  2. chenmo chenmo

    好样的!感谢分享。

添加新评论