部署教程
将下方代码放置在主题目录下的function.php或者新建一个func.php文件
// 注册自定义 REST API 接口
function register_hot_comments_endpoint() {
register_rest_route('myapi/v1', '/hot-comments', array(
'methods' => 'GET',
'callback' => 'get_hot_comments',
));
}
add_action('rest_api_init', 'register_hot_comments_endpoint');
function get_hot_comments() {
$comments = get_comments(array(
'number' => 50, // 获取50条最新评论
'status' => 'approve',
'orderby' => 'comment_date',
'order' => 'DESC',
));
$data = [];
if (empty($comments)) {
return new WP_REST_Response([], 200);
}
foreach ($comments as $comment) {
$avatar_html = zib_get_data_avatar($comment->comment_author_email);
preg_match('/src=["\'](\/\/[^"\']+)["\']/', $avatar_html, $matches);
$avatar_url = !empty($matches[1]) ? 'https:' . $matches[1] : '';
if (!$avatar_url) {
$avatar_url = get_template_directory_uri() . '/img/avatar-default.png';
}
$comment_url = get_comment_link($comment->comment_ID);
$user_url = get_author_posts_url($comment->user_id);
$data[] = [
'post_id' => $comment->comment_post_ID,
'author' => $comment->comment_author,
'content' => $comment->comment_content,
'avatar' => $avatar_url,
'url' => get_permalink($comment->comment_post_ID),
'comment_url' => $comment_url,
'user_url' => $user_url,
];
}
return new WP_REST_Response($data, 200);
}
如果只希望在首页显示,可以通过后台小工具 → 自定义 HTML,将代码放在首页的任何位置。
如果希望全站显示,则可以将代码放在主题设置中的自定义 HTML
<style>
#wniui-popup-window {
min-width: 300px;
max-width: 500px;
bottom: 20px;
right: 20px;
position: fixed;
z-index: 1002;
color: #363636;
padding: 8px 16px;
border-radius: 12px;
transition: opacity 0.3s ease, transform 0.3s ease;
background-color: rgba(255, 255, 255, 0.85);
border: 1px solid #e3e8f7;
max-height: 300px;
opacity: 0;
transform: translateY(20px);
display: flex;
flex-direction: column;
justify-content: flex-start;
transition: .3s;
cursor: pointer;
}
#wniui-popup-window:hover {
border: 1px solid #425AEF;
transition: .3s;
}
#wniui-popup-window.wniui-show {
opacity: 1;
transform: translateY(0);
}
.wniui-popup-header {
position: relative;
display: flex;
align-items: center;
}
.wniui-popup-title {
font-size: 14px;
font-weight: bold;
background: #363636;
color: #fff;
padding: 4px 8px;
border-radius: 4px;
margin-right: 8px;
transition: .3s;
}
.wniui-popup-title:hover {
background-color: #423AEF;
transition: .3s;
}
.wniui-popup-author {
font-size: 14px;
font-weight: 600;
color: #363636;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
}
.wniui-popup-avatar {
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 6px;
background-color: #f5f6f7;
}
.wniui-popup-window-divider {
width: 100%;
height: 1px;
background: #e3e8f7;
margin: 5px 0;
}
.wniui-popup-window-content {
font-size: 15px;
word-wrap: break-word;
max-width: 450px;
white-space: normal;
text-overflow: ellipsis;
}
.wniui-popup-window-content p {
margin: 0;
padding: 0;
line-height: 1.5;
}
@media screen and (max-width: 768px) {
#wniui-popup-window {
display: none !important;
}
}
.wniui-popup-author span:hover{
color:#425AEF;
transition: .3s;
}
svg#popup-link:hover path {
fill: #425AEF;
transition: .3s;
}
</style>
<div id="wniui-popup-window" class="wniui-show-popup-window" style="cursor: pointer;">
<div class="wniui-popup-header">
<span class="wniui-popup-title">热评</span>
<span class="wniui-popup-author"></span>
<svg id="popup-link" style="transition: .3s; cursor: pointer;display: flex; position: absolute;right:0px;" t="1740280523955" class="icon" viewbox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="22033" xmlns:xlink="http://www.w3.org/1999/xlink" width="30" height="30">
<path
d="M512.1 137.8c-206.4 0-373.7 167.3-373.7 373.7s167.3 373.7 373.7 373.7 373.7-167.3 373.7-373.7-167.3-373.7-373.7-373.7zM721 508.5L589.2 647c-9.9 10.4-27.4 3.4-27.4-11v-90.9h-1.4c-130.9 0-239.1 58.4-259.2 134.7h-2.3c12.8-133.2 125-237.4 261.5-237.4 0.5 0 0.9 0.1 1.4 0.1V359c0-14.4 17.5-21.4 27.4-11L721 486.6c5.8 6.2 5.8 15.8 0 21.9z"
fill="#231815" p-id="22034"></path>
</svg>
</div>
<div class="wniui-popup-window-divider"></div>
<div class="wniui-popup-window-content">
</div>
</div>
<script>
class CommentPopup {
constructor(config) {
this.config = {
displayTime: 5000,
fadeTime: 300,
retryInterval: 3000,
apiUrl: 'https://你的域名/wp-json/myapi/v1/hot-comments',
emojiPath: 'https://你的域名/wp-content/themes/zibll/img/smilies/',
defaultAvatar: 'https://你的域名/wp-content/themes/zibll/img/avatar-default.png',
...config
};
this.popupTimer = null;
this.retryTimer = null;
this.commentData = [];
this.currentCommentUrl = '';
this.popup = document.getElementById('wniui-popup-window');
this.bindEvents();
}
async init() {
try {
await this.fetchComments();
this.showRandomComment();
} catch (error) {
console.error('Failed to fetch comments:', error);
this.scheduleRetry();
}
}
async fetchComments() {
const response = await fetch(this.config.apiUrl);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
this.commentData = await response.json();
}
scheduleRetry() {
this.retryTimer = setTimeout(() => this.init(), this.config.retryInterval);
}
showRandomComment() {
if (this.commentData.length === 0) return;
const post = this.commentData[Math.floor(Math.random() * this.commentData.length)];
const content = this.sanitizeContent(decodeURIComponent(post.content));
if (!content) return;
const data = {
avatar: post.avatar || this.config.defaultAvatar,
author: post.author,
content,
postUrl: post.url,
commentUrl: post.comment_url,
authorUrl: post.user_url || '#'
};
this.updatePopup(data);
}
sanitizeContent(content) {
return content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}
updatePopup(data) {
clearTimeout(this.popupTimer);
this.popup.classList.remove('wniui-show');
this.currentCommentUrl = data.commentUrl;
setTimeout(() => {
this.renderPopupContent(data);
this.popup.classList.add('wniui-show');
this.scheduleNextComment();
}, this.config.fadeTime);
}
renderPopupContent(data) {
const authorElement = this.popup.querySelector('.wniui-popup-author');
authorElement.innerHTML = `
<img class="wniui-popup-avatar" src="${data.avatar}" alt="avatar" loading="lazy">
<span onclick="window.location.href='${data.authorUrl}'">${data.author}</span>
`;
this.popup.querySelector('.wniui-popup-window-content').innerHTML = `<p>${data.content}</p>`;
}
scheduleNextComment() {
this.popupTimer = setTimeout(() => {
this.hidePopup();
this.showRandomComment();
}, this.config.displayTime);
}
hidePopup() {
this.popup.classList.remove('wniui-show');
}
handlePopupClick = (event) => {
if (event.target.closest('svg#popup-link') || !event.target.closest('.wniui-popup-author')) {
if (this.currentCommentUrl) {
window.location.href = this.currentCommentUrl;
}
}
}
bindEvents() {
this.popup.addEventListener('click', this.handlePopupClick);
let touchStartY = 0;
this.popup.addEventListener('touchstart', (e) => {
touchStartY = e.touches[0].clientY;
});
this.popup.addEventListener('touchmove', (e) => {
const touchDiff = e.touches[0].clientY - touchStartY;
if (touchDiff > 50) {
this.hidePopup();
}
});
}
destroy() {
clearTimeout(this.popupTimer);
clearTimeout(this.retryTimer);
this.popup.removeEventListener('click', this.handlePopupClick);
}
}
const commentPopup = new CommentPopup({
displayTime: 5000,
fadeTime: 300,
retryInterval: 3000
});
commentPopup.init();
window.addEventListener('unload', () => {
commentPopup.destroy();
});
</script>



没有回复内容