Tiếp nối bài viết trước “Sử dụng Memos để xây dựng mạng xã hội độc lập, ba yếu tố self-host đã hoàn chỉnh”. Bài viết này sẽ trình bày:
- Cách thêm bình luận Artalk vào ứng dụng Memos.
- Tích hợp trang đơn Memos vào Typecho và thêm bình luận Artalk.
Thêm Bình Luận Artalk Vào Ứng Dụng Memos
Trước tiên, bạn cần tự thiết lập dịch vụ 12 chòm sao bình luận Artalk, có thể tham khảo tài liệu chính thức, ở đây sẽ không đi sâu vào chi tiết.
Sau đó, trong phần Cài đặt - Hệ thống
của Memos, thêm kiểu tùy chỉnh và script tùy chỉnh.
- Thêm đoạn mã sau vào script tùy chỉnh Thay thế các thông số liên quan đến Artalk bằng của riêng bạn.
// artalk comments
// css
document.head.innerHTML += '<link rel="stylesheet" href=" type="text/css"/>';
// js
function addArtalkJS() {
var memosArtalk = document.createElement("script");
memosArtalk.src = `
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') || ''; // phiên bản 0.12.x vui lòng thay '.memo-wrapper' bằng '.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 = "Đang tải bình luận..."
}
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: '
site: 'Skyue Weibo',
darkMode: 'auto'
});
Artalk.on('list-loaded', function() {
// console.log('Bình luận đã được tải xong');
memoLoading.innerHTML = ''
startArtalk();
});
}, 1000);
}
}
//console.log(window.location.href);
}, 1000)
}
startArtalk();
- Thêm đoạn mã sau vào kiểu tùy chỉnh
a.time-text:after { content: ' Bình luận 💬 '; }
.atk-main-editor { margin-top: 20px; }
Kết quả cuối cùng tỷ số bóng đá hôm nay như sau:

Tích Hợp Memos Trang Đơn Vào Typecho Và Thêm Bình Luận
Hãy cùng ngắm nhìn kết quả sau khi tích hợp, như hình dưới đây. Điểm nổi bật là: Khung bình luận mặc định được gập lại, khi nhấp vào bình luận thì khung bình luận sẽ mở ra trên trang hiện tại mà không cần chuyển hướng, tương tự u88 casino như Weibo
Trên internet có rất nhiều ví dụ về ứng dụng trang đơn Memos, ví dụ như phiên bản do thầy Mộc phát triển mà tôi đã sử dụng trong một thời gian.
Blog của tôi được xây dựng bằng Typecho, có máy chủ phía sau, lần này tôi trực tiếp tạo một tệp mẫu memos.php
trong thư mục chủ đề (tôi đang sử dụng chủ đề mặc định), và lấy dữ liệu Memos từ máy chủ phía sau để hiển thị, mã nguồn như sau:
<?php $this->need('header.php'); ?>
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/*
*/
?>
<div class="col-mb-12 col-8" id="main" role="main">
<article class="post"><h2 class="post-title"></h2><article>
<?php
$url = ' // Không giới hạn loại nội dung
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Bỏ qua kiểm tra chứng chỉ
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // Kiểm tra thuật toán mã hóa SSL từ chứng chỉ
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 'Lỗi tải weibo';
}
curl_close($ch);
$array_data = json_decode($response,true)['data'];
for($i=1; $i<count($array_data); $i++)
{
$obj = $array_data[$i];
// Điều kiện if này chỉ hiển thị Memos trong 30 ngày gần nhất
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); // Sử dụng trình phân tích Markdown tích hợp của Typecho để phân tích Memos
$body_html = sprintf('
<div class="memo-top-wrapper">Tháng Mười · %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.'">Bình luận</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.'">Bình luận</span>(<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>)</a><div style="display: none;" id="memo_'.$memo_id.'"></div></article>';
} // Mã HTML được echo, thuộc tính onclick gọi hàm tải khung bình luận Artalk bên dưới, cần truyền tham số memo_id
}
}
?> <!-- Xử lý dữ liệu Memos kết thúc -->
<div class="memo-bottom">Xem thêm nội dung tại trang chủ weibo</div>
</div>
<!-- Tập tin artalk -->
<link href=" rel="stylesheet">
<script src="
<!-- Đoạn JS này sẽ kích hoạt khi nhấn nút bình luận trên trang, hỗ trợ mở rộng và thu gọn khung bình luận -->
<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 = 'Thu gọn bình luận';
new Artalk({
el: '#memo_' + memo_id, // Selector phần tử liên kết
pageKey: '/m/'+memo_id, // Cố định
pageTitle: 'Skyue Weibo', // Tiêu đề trang (để trống sẽ tự động lấy)
server: ' // Địa chỉ phía sau
site: 'Skyue Weibo', // Tên trang web được tạo trong phía sau
});
}
else{
commentDiv.style.display='none';
commentBtn.innerHTML = 'Bình luận';
}
}
</script>
<!-- Đoạn JS này sẽ hiển thị số lượng bình luận khi chưa mở rộng -->
<script>
Artalk.loadCountWidget({
server: '
site: 'Skyue Weibo',
pvEl: '#ArtalkPV',
countEl: '#ArtalkCount',
});
</script>
<?php $this->need('footer.php'); ?>
Đoạn mã trên thực hiện hai chức năng:
- Lấy dữ liệu Memos thông qua API và hiển thị trực tiếp trên máy chủ.
- Cung cấp hai đoạn mã javascript, một dùng để hiển thị số lượng bình luận, một dùng để mở rộng và thu gọn khung bình luận.
Nếu bạn đang sử dụng chương trình blog Typecho, rất có khả năng có thể sử dụng đoạn mã trên, chỉ cần điều chỉnh địa chỉ API Memos cũng như hai tham số server
và site
trong hàm loadArtalk theo tình huống của bạn.
Về chức năng nhấn nút “Bình luận”, có ba điểm mấu chốt:
- Trong mẫu, mỗi memo đều có sẵn một container
div
, vớiid
làmemo_{memo_id}
, ví dụ<div id="memo_1"></div>
. Nó được sử dụng để tải khung bình luận dưới mỗi memo tương ứng. - Thêm thuộc tính
onclick
cho nút “Bình luận”, gọi hàmloadArtalk
và truyền tham sốmemo_id
. Khi đoạn mã JS này được thực thi, nó sẽ tìm kiếm container được đề cập ở trên, tải khung bình luận và hiển thị các bình luận tương ứng của Memo. Khi nhấn lại ở trạng thái mở rộng, nó sẽ thu gọn. - Số lượng bình luận trong dấu ngoặc của nút “Bình luận” được thực hiện bởi
<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>
.
Dưới đây là các kiểu CSS được thêm vào file style.css trong thư mục chủ đề:
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;
}
Chỉ vậy thôi, làm việc suốt đêm thứ bảy đến 4 giờ sáng hôm sau, may mắn có ChatGPT giúp đỡ.
Ngoài ra, vẫn còn một số chỗ chưa hoàn hảo, ví dụ:
- Hiện tại hình ảnh được sắp xếp thẳng hàng dọc, chưa làm thành lưới hình chín ô.
- Chưa có trang chi tiết, khi mở liên kết thông báo bình luận Memos vẫn dẫn đến trang memos.skyue.com.
Để lại lỗ hổng, khi nào rảnh sẽ giải quyết hai vấn đề này, đặc biệt là vấn đề thứ hai, rất muốn thực hiện trang chi tiết Memos trên trang chủ www.skyue.com, về mặt kỹ thuật chắc chắn khả thi, chỉ là bây giờ chưa biết cách.
Sửa đổi lần cuối vào 2025-04-26