span - chuyển nhượng
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 thành phần tự lưu trữ đã hoàn chỉnh”. Bài viết này sẽ giới thiệu:
- Cách thêm bình luận Artalk vào ứng dụng Memos
- Cách tích hợp trang đơn Memos vào Typecho và thêm bình luận Artalk
Thêm Artalk Bình Luận vào Ứng Dụng Memos
Trước tiên, bạn cần tự thiết lập dịch vụ 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.
Sau đó, trong mục Cài đặt - Hệ thống
của Memos, thêm phong cách tùy chỉnh và kịch bản tùy chỉnh.
- Thêm đoạn mã sau vào kịch bản tùy chỉnh Thay thế các thông số liên quan đến Artalk bằng thông tin riêng của 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 hãy 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 Blog',
darkMode: 'auto'
});
Artalk.on('list-loaded', function() {
// console.log('Bình luận đã tải xong');
memoLoading.innerHTML = ''
startArtalk();
});
}, 1000);
}
}
//console.log(window.location.href);
}, 1000)
}
startArtalk();
- Thêm đoạn mã sau vào phong cách 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 như sau: ![]
Tích Hợp Memos Trang Đơn Vào Typecho xem kết quả tỷ số bóng đá 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 bên dưới. Điểm nổi bật là: Khung bình luận mặc định được gập lại, khi nhấn bình luận thì khung mở ra trên cùng trang hiện tại mà không cần chuyển trang, tương tự như Weibo
Trên mạng có 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 một thời chuyển nhượng 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ủ để 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 blog';
}
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 có sẵn của Typecho để xử lý Memos
$body_html = sprintf('
<div class="memo-top-wrapper">Skyue · %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, 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 tại trang chủ blog</div>
</div>
<!-- Tập tin artalk -->
<link href=" rel="stylesheet">
<script src="
<!-- Đoạn JS này được kích hoạt khi nhấp 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ử gắn kết
pageKey: '/m/'+memo_id, // Cố định
pageTitle: 'Skyue Blog', // Tiêu đề trang (rời trống để tự động lấy)
server: ' // Địa chỉ backend
site: 'Skyue Blog', // Tên trang được tạo trong backend
});
}
else{
commentDiv.style.display='none';
commentBtn.innerHTML = 'Bình luận';
}
}
</script>
<!-- Đoạn js này hiển thị số lượng bình luận khi chưa mở rộng -->
<script>
Artalk.loadCountWidget({
server: '
site: 'Skyue Blog',
pvEl: '#ArtalkPV',
countEl: '#ArtalkCount',
});
</script>
<?php $this->need('footer.php'); ?>
Mã nguồn 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 đoạn hiển thị số lượng bình luận, đoạn còn lại cho phép mở rộng và thu gọn khung bình luận.
Nếu bạn sử dụng chương trình blog Typecho, rất có thể mã nguồn trên có thể áp dụng, chỉ cần điều chỉnh địa chỉ API Memos và 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”, trọng điểm nằm ở ba phần sau:
- Trong mẫu, mỗi memo đều có một container
div
, vớiid
làmemo_{memo_id}
, ví dụ<div id="memo_1"></div>
. Nó 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ã javascript này chạy, nó sẽ tìm container được đề cập ở trên, tải khung bình luận và hiển thị bình luận của Memo tương ứng. Nếu đang ở trạng thái mở rộng, nhấn lại 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 tạo bởi
<span id="ArtalkCount" data-page-key="/m/'.$memo_id.'"></span>
.
Dưới đây là kiểu dáng bổ sung trong tệp style.css của 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, may mắn có ChatGPT giúp đỡ.
Ngoài ra, vẫn còn một số điểm chưa hoàn hảo:
- Hiện tại hình ảnh được xếp dọc, chưa làm thumbnail dạng lưới chín ô.
- Chưa có trang chi tiết, khi mở thông báo bình luận từ email vẫn dẫn đến trang memos.skyue.com.
Để lại vấn đề này, khi 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 www.skyue.com, kỹ thuật chắc chắn khả thi, chỉ là hiện tại chưa biết cách.