在个人博客中加上Memos记录展示。

科技   科技   2024-12-26 10:32   江苏  
戳上方“执行上下文”,选择“置顶公众号

关键时刻,第一时间送达!


什么是 memos?

memos 是「一个具有知识管理和社交网络的开源、自我托管的备忘录中心」。这是一个类似私人微博的产品,支持标签、过滤、搜索、多账户,可以自用也可以和朋友一起使用,用来碎片化的记录信息,就像 flomo 一样。除了以上它还可以是一个免费的自托管知识库。

TA 能做什么?

你可以部署在自己的服务器,当作私人的微博、朋友圈、记录载体、知识库、笔记等。他可以支持 markdown 输入,也可以添加标签、附件📎等多种形式。

如何部署?

可以直接使用 docker 进行安装。

docker run -d --name memos -p 5230:5230 -v ~/.memos/:/var/opt/memos neosmemo/memos:latest

或者像我一样在宝塔面板中选择 docker- 应用-memos 直接进行安装。安装完成后再网站中新增一个 memos 网址 并设置反向代理到 docker 部署的 memos 服务的应用端口地址上。

更多安装教程可以直接搜索 memos 安装教程。

在个人博客和小程序中添加 memos 信息展示页面

有的时候想随时记录下当前的一个心情、状态、或者要做的事情,那么对于博客来说可能有点不合适,因为对于rss 来说可能有太多不是正式的内容。所以在搭建 memos 后,发现TA有对外的 api。所以就想着把 memos 的状态更新到自己的博客上面。效果如下:

web端博客

博客小程序中(可以直接点击👇下面图片体验小程序)

实现方式

在小程序中,实现很简单只需要调取 memos 的 memos 接口,默认会返回当前所有的记录,在小程序中渲染即可。请求的时候需要带上 token 并且做好懒加载和分页即可。

  fetchMemos: function (pageToken = '', limit = 20{
    const self = this;
    wx.request({
      url`https://demo.memos.cn/api/v1/memos?pageToken=${pageToken}&pageSize=${limit}&creatorId=1`,
      method'GET',
      header: {
        'Authorization''Bearer ' + 'token',
        'Content-Type''application/json',
      },
      success(res) => {
        if (res.statusCode === 200) {
          const newMemos = res.data.memos;
          const pageToken = res.data.nextPageToken;
          const mdata = this.data.memosData.concat(newMemos);
          mdata.forEach((item) => {
            item.newcreateTime = self.formatTimeAgo(item.createTime)
          })
          self.setData({
            memosData: mdata,
            pageToken: pageToken,
          });
        }
      },
    });
  },

在个人博客上如何实现呢?因为博客使用的 WordPress ,所以你需要在你的主题目录中新建一个单页模板文件,用来显示 memos 信息。

首先在你的博客安装目录中的主题文件目录下的 pages 目录中新建一个单页模板。同时设置信息如下:

<?php
/* Template Name: Memos Page*/
get_header();
?>

然后在博客后台新建页面,选择页面模板为刚刚设置的memos pages,然后将该页面添加到你的菜单中。

接下来在模板页面添加相关逻辑代码。

html 部分

<div id="primary" class="content-area">
    <main id="main" class="site-main">
        <h3>碎碎念</h3>
        <div id="memos-container" class="memos-container"></div>
        <div id="loading" class="loading-text" style="display: none;">加载中...</div>
        <div id="no-more-data" class="no-more-data" style="display: none;">没有更多数据了</div>
    </main>
</div>

JavaScript部分

<script>
    let isLoading = false
    let hasMoreData = true;
    function loadMemos(pageToken = '') {
        if (isLoading || !hasMoreData) return;
        isLoading = true;
        document.getElementById('loading').style.display = 'block';
        fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
            method: 'POST',
            headers: {
                'Content-Type''application/x-www-form-urlencoded',
            },
            body: `action=load_memos&pageToken=${pageToken}`,
        })
        .then(response => response.json())
        .then(data => {
            isLoading = false;
            document.getElementById('loading').style.display = 'none';
            if (data && data.memos && Array.isArray(data.memos) && data.memos.length > 0) {
                const memosContainer = document.getElementById('memos-container');
                data.memos.forEach(memo => {
                    const existingMemo = Array.from(memosContainer.children).find(child => child.dataset.id === memo.id);
                    if (!existingMemo) {
                        const memoElement = document.createElement('div');
                        memoElement.className ='memo-item'
                        memoElement.dataset.id = memo.id;
                        let tagsHtml = '';
                        if (memo.property && memo.property.tags && memo.property.tags.length > 0) {
                            tagsHtml = `<div class="memos-tags">${memo.property.tags.map(tag => `<div class="tags">#${tag}</div>`).join('')}</div>`;
                        }
                        memoElement.innerHTML = `
                            <div class="memos-info">
                                <div class="memos-info-avator">
                                    <img class="memos-info-avator" src="avator.jpeg" alt="">
                                </div>
                                <div class="memos-info-right">
                                    <div class="memos-info-username">坚果大叔</div>
                                    <div class="memos-info-time">${memo.formattedTime}</div>
                                </div>
                            </div>
                            <div class="memos-content">${memo.content}</div>
                            ${tagsHtml}
                        `;
                        memosContainer.appendChild(memoElement);
                    }
                });
                // pageToken = data.nextPageToken; 
                localStorage.setItem('nextPageToken', data.nextPageToken);
                if (!data.nextPageToken) {
                    hasMoreData = false;
                    document.getElementById('no-more-data').style.display = 'block';
                }
            } else {
                hasMoreData = false;
                document.getElementById('no-more-data').style.display = 'block';
            }
        })
        .catch(error => {
            console.error('加载数据失败:', error);
            isLoading = false;
            document.getElementById('loading').style.display = 'none';
        });
    }
    window.addEventListener('scroll'function () {
        if (isLoading || !hasMoreData) return
        const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
        const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
        if (scrollTop + clientHeight >= scrollHeight - 140) {
            let pageToken = localStorage.getItem('nextPageToken') || ''
            loadMemos(pageToken);
        }
    });
    document.addEventListener('DOMContentLoaded'function () {
        loadMemos();
    });
</script>

因为需要分页加载,所以你还需要在你的博客目录下的 functions.php 中添加接口请求的功能。

add_action('wp_ajax_load_memos''handle_load_memos');
add_action('wp_ajax_nopriv_load_memos''handle_load_memos');
function handle_load_memos() {
    $pageToken = sanitize_text_field($_POST['pageToken'] ?? '');
    $limit = 20;
    $response = wp_remote_get("https://demo.memos.cn/api/v1/memos?pageToken={$pageToken}&pageSize={$limit}&creatorId=1"array(
        'headers' => array(
            'Authorization' => 'Bearer token',
            'Content-Type' => 'application/json',
        ),
    ));
    if (is_array($response) && !is_wp_error($response)) {
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        if (!empty($data['memos'])) {
            foreach ($data['memos'as &$memo) {
                $memo['formattedTime'] = formatTimeAgo($memo['createTime']);
            }
            wp_send_json(array(
                'memos' => $data['memos'],
                'nextPageToken' => $data['nextPageToken'] ?? '',
            ));
        }
    }
    wp_send_json(array(
        'memos' => []
        'nextPageToken'
    ));
    wp_die();
}

将上面文件都保存完成后,就可以在你的博客成功显示 memos的内容了。

但是因为安装版本的 memos 的问题,api 返回的数据中只有文本信息,上传的多媒体内容并没有返回,这个问题还没有解决,还在查看 api 文档。后续一并更新解决。

从前ing




执行上下文
一枚佛系前端开发,会一丢丢摄影,喜欢折腾,爱好美食,分享点学习经验、见闻、笔记、技巧!