本篇魔改教程只适用于 Twikoo评论 ,其他评论系统可自行修改适配。
在20241224更新
中优化了很多东西,包括教程的上手难度都做出了很多的调整,小白也可以快速上手。
效果预览
创建数据 小节开始前,提醒事项。 对于初次魔改新手,建议先过一遍:魔改前置教程:添加自定义css和js文件
创建[博客根目录]/source/comments/index.md
文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 --- title: 最新评论 date: 2023-07-17 14:07:01 type: comments top_img: false aside: false top_ page: truetop_bg: https://img.meuicat.com/banner top_ item: 速览top_title: 最新评论 top_ tips: 快速预览本站最新评论--- <!-- 页面内容 -->
修改[主题目录]/layout/page.pug
来使页面匹配。
1 2 3 4 5 6 7 when 'shuoshuo' include includes/page/shuoshuo.pug + when 'comments' + include includes/page/comments.pug default include includes/page/default-page.pug +commentLoad
新建[主题目录]/layout/includes/page/comments.pug
页面,并新增以下内容。
1 2 3 #comments-page .page-load img(src="https://img.meuicat.com/blog/loading.svg" style="margin:auto")
新建[主题目录]/source/css/_page/comment.styl
样式文件,并新增以下内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 #comments-page display : flex flex-wrap : wrap gap : 12px .comment-card position : relative width : calc (100% / 4 - 36px / 4 ) border-radius : 12px outline : var (--icat-border-always) padding : 12px overflow : hidden box-shadow : var (--icat-shadow-border) background : var (--icat-card-bg) animation : slide-in .6s .4s backwards +maxWidth768 () width : 100% &:hover .comment-more opacity : 1 .comment-info display : flex align-items : center padding-bottom : 12px margin-bottom : 8px border-bottom : var (--icat-border-dashed) gap : 12px img width : 50px height : 50px object-fit : cover border-radius : 50% margin : 0 !important .comment-information display : flex flex-direction : column line-height : 1.5 .comment-user display : flex align-items : center font-weight : bold font-size : 15px .comment-author :after content : "\e00c" font-family : "MeuiCat" !important padding-left : 6px font-size : 14px color : var (--icat-theme) .comment-time color : var (--icat-secondtext); font-size : 12px .comment-content margin : 8px 5px 0 overflow : hidden text-overflow : ellipsis display : -webkit-box -webkit-box-orient: vertical -webkit-line-clamp: 2 font-size : 14px font-weight : 400 line-height : 1.7 .comment-more position : absolute inset : 0 height : 100% width : 100% z-index : 1 background : var (--icat-theme) color : var (--icat-card-bg) margin : 0 display : flex padding : .5rem 1rem opacity : 0 flex-direction : column justify-content : space-between transition : .3s ease-out .comment-title display : flex align-items : center justify-content : space-between span overflow : hidden text-overflow : ellipsis display : -webkit-box -webkit-box-orient: vertical -webkit-line-clamp: 1 font-weight : 700 cursor : pointer i margin-right : 4px a font-size : 14px color : var (--icat-card-bg) opacity : .6 margin-left : 4px white-space : nowrap #comment-tool display : flex flex-wrap : wrap gap : 4px 8px a background : var (--icat-sparent) color : var (--icat-card-bg) border-radius : 8px padding : 4px 8px font-size : 14px opacity : .6 a :hover opacity 1 !important
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 let commentDataconst comment = { fetchData : async (option) => { const res = await fetch ('{envId}' , { method : "POST" , body : JSON .stringify ({ "event" : "GET_RECENT_COMMENTS" , "accessToken" : "{YOUR_TOKEN}" , "includeReply" : true , "pageSize" : -1 , ...option }), headers : { 'Content-Type' : 'application/json' } }).then (res => res.json ()) return res.data }, new : async (type, exclude) => { const comments = document .getElementById ('comments-page' ) if (!comments) return const commentclick = ( ) => { document .querySelectorAll ('#comment-tool a' ).forEach (e => e.addEventListener ('click' , comment.operate ) ) } const [a, b, c] = [`<a href="javascript:void(0)" data-type="post" title="显示此文章所有评论">查看更多</a>` , `<a href="javascript:void(0)" data-type="visitor" title="显示该评论者的所有评论">查看Ta更多评论</a>` , `<a href="javascript:void(0)" data-type="all" title="查看本站最新评论">返回评论</a>` ] let data, tool, html = '' if (!commentData) commentData = await comment.fetchData () data = commentData if (type) data = data.filter (item => item[type] === exclude), tool = type === 'mailMd5' ? a + c : b + c else data = data.slice (0 , 50 ), tool = a + b if (!ArticleData ) await toRandomPost (true ) data.forEach (item => { const time = changeTime (item.created , true ) const title = Object .values (ArticleData ).flatMap (data => data).find (article => article.link === item.url )?.title || '未知标题' html += `<div class="comment-card"><div class="comment-info"><img src="${item.avatar} "><div class="comment-information"><span class="comment-user ${item.mailMd5 === '91afb88f9ce8126f2825f7ef9fd64ceb' ? 'comment-author' : '' } " data-mailmd5="${item.mailMd5} ">${item.nick} </span><span class="comment-time">${time} </span></div></div><div class="comment-content">${item.commentText.trim()} </div><div class="comment-more"><div class="comment-title"><span class="comment-link" title="查看此文章" onclick="pjax.loadUrl('${item.url} ')"><i class="iconfont icat-read"></i>${title} </span><a href="javascript:void(0)" onclick="pjax.loadUrl('${item.url} #${item.id} ')">查看评论</a></div><div id="comment-tool">${tool} </div></div></div>` }) comments.innerHTML = html commentclick () }, operate : (event ) => { const type = event.target .getAttribute ('data-type' ) const commentCard = event.target .closest ('.comment-card' ) if (type === 'visitor' ) comment.new ('mailMd5' , commentCard.querySelector ('.comment-user' ).getAttribute ('data-mailmd5' )) if (type === 'post' ) comment.new ('url' , commentCard.querySelector ('.comment-link' ).getAttribute ('onclick' ).split ("'" )[1 ]) if (type === 'all' ) comment.new () } } btf.addGlobalFn ('pjaxComplete' , comment.new (), 'comment' )
{envId} 和 {YOUR_TOKEN} 需要替换为对应值
Token获取
注意事项 如果你此前并未实现随机文章 功能,则需要进行下面的操作。
新增[主题目录]/scripts/helpers/articles_json.js
文件,新增以下内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 'use strict' hexo.extend .generator .register ('thePages' , function (locals ) { const postData = locals.posts .filter (post => post.random !== false ) .map (post => { const date = new Date (post.date ); const formattedDate = date.toISOString ().split ('T' )[0 ]; return { title : post.title || "暂无标题" , time : formattedDate, update : post.updated ? new Date (post.updated ).toISOString ().replace ('T' , ' ' ).split ('.' )[0 ] : formattedDate, link : post.permalink .replace (/^(?:\/\/|[^/]+)*\// , '/' ), cover : post.cover || hexo.theme .config .default_top_img } }) .sort ((a, b ) => new Date (b.time ) - new Date (a.time )) const exclude = ['.js' , '.wechatOA' , '.json' ]; const pageData = locals.pages .filter (page => {return page.random !== false && !exclude.some (ext => page.source .endsWith (ext));}) .map (page => { const date = new Date (page.date ); const formattedDate = date.toISOString ().split ('T' )[0 ]; return { title : page.title || "暂无标题" , time : formattedDate, link : page.permalink .replace (/^(?:\/\/|[^/]+)*\// , '/' ).replace (/\/index\.html$/ , '/' ) } }) const jsonData = { post : postData, page : pageData } return { path : 'articles.json' , data : JSON .stringify (jsonData) } })
打开[博客根目录]/source/js/meuicat.js
文件,新增以下内容。
1 2 3 4 5 let ArticleData const toRandomPost = async ( ) => { if (!ArticleData ) ArticleData = await fetch ('/articles.json' ).then (res => res.json ()) }
进阶适配 Butterfly的魔改教程:评论弹窗
热评?评论!PC端文章右下角评论弹窗功能
旧版教程 引用站外地址,注意辨别
Butterfly的魔改教程:最新评论页
显示全站最新评论内容,快速预览;内附评论总数显示、热评弹窗教程
更新历史
230821 更新:新增article的JSON文件原生api,再也不用手动新增结构数据啦~
230720 更新:修复控制台无容器时报错
230718 更新:修复个人卡片显示评论数量异常。新增作者标识,提升UI样式
240628 更新:新增评论过滤匹配功能;调整、减少冗余UI样式以及JS优化
240702 更新:热评弹窗优化、UI调整、教程地址更新
241224 更新:教程更新、优化代码,修复已知问题
Butterfly的魔改教程:最新评论页
此文章版权归 MeuiCat 所有,完整转载,请注明来源!