前言
看@Shine在博客里整了个点赞功能Qexo添加点赞功能,心动,那就行动。
懒得整一个Qexo系统,那就看看有木有现成的点赞系统拿来改改用。找到力orlike-vercel
最终效果:
实现
部署OrLike
注册登录leancloud,最好是国际版,创建一个应用,名称随意。在侧栏找到数据存储->结构化数据,点击创建Class,名称为OrLike,默认ACL权限修改为所有用户。
接着在侧栏找到设置->应用凭证,复制AppID和AppKey,后续用到。
数据库设置完成,点击下面链接部署后端到Vercel。
部署完成后,在该Vercel项目的设置中找到环境变量,填入名为APPID(值对应之前复制的AppID)和APPKEY(对应AppKey)的环境变量,然后重新部署。
由于vercel默认域名被墙,最好绑定自己的二级域名,该域名链接即为api。
前端部署
以Hexo-butterfly主题框架为例:
修改layout\includes\post\reward.pug,在末尾添加以下代码。
#orlike-box.orlike-box script. (() => { function loadOrLike () { new OrLike({ serverUrl: "你的api", el: ".orlike-box", days: 30, }); } window.pjax ? loadOrLike() : window.addEventListener('load', loadOrLike) })() 修改layout\includes\header\post-info.pug,在末尾添加以下代码,注意缩进在**.meta-firstline**内。
span.post-meta-orlike i.iconfont.icon-aixin.fa-fw.post-meta-icon span.post-meta-label= '点赞数:' a(href=url_for(page.path) + '#orlike-box') span.orlike-count在配置文件中全局引入该js和JQ:
const version = "V0.1.33"; function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); var expires = "expires=" + d.toGMTString(); document.cookie = cname + "=" + cvalue + "; " + expires; }function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i].trim(); if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return "";}function createLink(url) { let link = $(document.createElement('link')); link.attr('href', url); link.attr('rel', 'stylesheet'); link.attr('type', 'text/css'); $('link').last().after(link); }function OrLike({ serverUrl = "", el = "", days = 30, style = "", ifont = "", icon = { like: "fa fa-thumbs-up", dislike: "fa fa-thumbs-down" }, } = {}) { this.serverUrl = serverUrl; this.el = el; this.style = style; this.ifont = ifont; this.days = days; this.icon = icon; this.ckid = ""; this.prepare(); this.init(); }OrLike.prototype.prepare = function () { $(this.el).addClass("orlike-loading"); if (this.style != "") { createLink(this.style); } if (this.ifont != "") { createLink(this.ifont); }}OrLike.prototype.init = function () { server_url = this.serverUrl; obj = this; $.ajax({ type: 'GET', url: server_url + '/tmp', dataType: 'jsonp', jsonp: "callback", jsonpCallback: "success", xhrFields: { withCredentials: true }, async: true, crossDomain: true, success: function (data) { let template = $(data.template); let icon_like = template.siblings("a.likeit.orlike").children("i"); let icon_dislike = template.siblings("a.dislikeit.orlike").children("i"); icon_like.attr('class', obj.icon.like); icon_dislike.attr('class', obj.icon.dislike); if (obj.icon.like == false) icon_like.remove(); if (obj.icon.dislike == false) icon_dislike.remove(); $(obj.el).removeClass("orlike-loading"); $(obj.el).html(template); obj.ckusr(obj); $('a.likeit.orlike').click({ obj: obj }, obj.like); $('a.dislikeit.orlike').click({ obj: obj }, obj.dislike); }, });}OrLike.prototype.ckusr = function (obj) { server_url = this.serverUrl; $.ajax({ type: 'GET', url: server_url + '/ckusr', dataType: 'jsonp', jsonp: "callback", jsonpCallback: "success", xhrFields: { withCredentials: true }, async: false, crossDomain: true, success: function (data) { if (data.stat == 'ok' && data.uid != "") { obj.ckid = data.ckid; if (!getCookie(data.ckid)) { setCookie(data.ckid, data.uid, obj.days); } obj.query(); } else { console.error('connect orlike failed!!!'); } }, });}OrLike.prototype.query = function () { server_url = this.serverUrl; $.ajax({ type: 'GET', url: server_url + '/qry?link=' + window.location.pathname, dataType: 'jsonp', jsonp: "callback", jsonpCallback: "success", xhrFields: { withCredentials: true }, crossDomain: true, success: function (data) { if (data.stat == 'ok') { $('a.likeit.orlike i span').text(data['like']); $('span.post-meta-orlike a span').text(data['like']); $('a.dislikeit.orlike i span').text(data['dislike']); } else { console.error('query orlike failed!!!'); } }, });}OrLike.prototype.orl = function (obj, method) { server_url = obj.serverUrl; req_url = server_url + '/orl?method=' + method + '&link=' + window.location.pathname + '&' + obj.ckid + '=' + getCookie(obj.ckid); $.ajax({ type: 'GET', url: req_url, dataType: 'jsonp', jsonp: "callback", jsonpCallback: "success", xhrFields: { withCredentials: true }, crossDomain: true, success: function (data) { obj.query(); }, }); }OrLike.prototype.like = function (event) { obj = event.data.obj; obj.orl(obj, 'like'); }OrLike.prototype.dislike = function (event) { obj = event.data.obj; obj.orl(obj, 'dislike'); }inject: head: bottom: - <script defer="true" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> - <script defer="true" src="/js/orlike.js"></script>引入CSS:
.orlike { color: rgba(255, 255, 255); font-size: 26px!important; line-height: 2; text-shadow: 5px 5px 5px #2ed0d9fc;}[data-theme=dark].orlike { color: rgba(255, 255, 255, 0.85); text-shadow: 4px 4px 4px #23a8af99;}.orlike:first-child{ margin-right: 36px;}.orlike span { margin-left: 0.3rem;}.orlike-box{ margin: 15px 0 0 0; display: flex; width: 100%; flex-direction: row; flex-wrap: nowrap; justify-content: center; position: relative; overflow: hidden; height: 52px;}.orlike:hover{ color: #f07e7e!important;}[data-theme=dark].orlike:hover{ color: #e87373e8!important;}.orlike-loading { display: block; height: 39px; width: 10px!important; border-radius: 50%; border: 2px solid #acacac; border-bottom-color: transparent; -webkit-animation: orlike-loadingRotate 0.75s linear infinite; animation: orlike-loadingRotate 0.75s linear infinite;}@-webkit-keyframes orlike-loadingRotate { 0% { -webkit-transform: rotate(0deg); } 50% { -webkit-transform: rotate(180deg); } 100% { -webkit-transform: rotate(360deg); }}@keyframes orlike-loadingRotate { 0% { transform: rotate(0deg); } 50% { transform: rotate(180deg); } 100% { transform: rotate(360deg); }}完毕。
后记
无
评论