Hexo_Fluid主题增加点赞、赞善按钮


Tags: #软件  #Hexo 
Created: 
Updated:

参考资料

leancloud相关

Netlify

为以下企业服务点赞😘

前言

前言废话文学,想看具体过程可以跳下面的注入器开始读起
实现还是要点时间的,如果时间宝贵,请火速赶往前方~

之前在穿越虫洞的时候,遇到别人博客下面有赞善按钮,就想着去实现

所幸,有跟我一样主题的博主,也有这方面有教程,照着教程的路子,前几天就实现了,具体可参考这篇

然后后面在穿越虫洞的时候,又又又又…发现了别人博客下有点赞按钮,

具体是这篇文章,看了之后很心动,又想要复刻

但这次搜索关键字(Fluid、点赞)没有找到相关的教程

没有办法,小白尝试下自己复刻,记录下实现过程(磨难过程)
所幸的是,磨出来了,有成果意味着成功,如果投入时间却没有成果出来,你会感觉付出不值得,那确实很打击人🤔

另外,我在这篇不建议大家折腾,要注重工具价值,好家伙,才过没两天,疯狂打自己脸,自己先折腾起来了😅

另外的另外,要感谢ChatGPT的大力支持,虽然有时候问东答西,要自己琢磨,但提供整体框架和代码还是非常舒服
如果自己纯手撸,要到哪时候🙃

接下来,小白跟着走,大佬看个乐~

配置

先写下配置,打开_config.yml,注意是根目录下的站点配置文件,而非主题配置文件_config.yml

将以下配置写入,剩下的信息,后面边配置,边填写

# 底部按钮组

bottom_btn:
  enable: true
  reward_btn:
    # 打赏按钮
    reward_btn_enable: true
    reward_btn_icon: 
    reward_btn_text: 打赏
    reward_btn_comment: "如果觉得本文对你有所帮助,请打赏——1元就足够感动我😘"
    qrcodes:
      - src: /images/wechatpay.jpg
        caption: 微信
        title: 微信赞赏码
      - src: /images/zhifubaopay.jpg
        caption: 支付宝
        title: 支付宝收款码
  like_btn:
    # 点赞按钮
    like_btn_enable: true
    like_btn_icon: 
    like_hover_btn_icon: 
    like_btn_text: 点赞
    leancloud_id: 
    leancloud_key: 
    serverUrl: 
  • reward_btn:打赏按钮配置
    • reward_btn_enable:是否开启打赏按钮
    • reward_btn_icon:打赏图标
    • reward_btn_comment:打赏用语
    • qrcodes:图片,照着上面设置即可,然后将二维码放在根目录\source\images即可
  • like_btn:点赞按钮配置
    • like_btn_enable:是否开启点赞按钮
    • like_btn_icon:点赞图标
    • like_hover_btn_icon:点赞后的图标
    • like_btn_text:点赞按钮默认显示的文本
    • leancloud_id:leancloud的应用ID
    • leancloud_key:leancloud的应用key
    • serverUrl:请求云函数的地址

注入器

Hexo 注入器 (opens new window) 是 Hexo 5 版本自身加入的一项新功能,所以在所有 Hexo 主题都是支持这个功能的。

先在根目录下新建个scripts,写一个JavaScript文件bottom-button-injector.js

作用:用于将两个按钮注入到Hexo页面中去

hexo.extend.injector.register('body_end', function () {

    // 打赏按钮变量,解包操作
    const {
        reward_btn_icon,
        reward_btn_text,
        reward_btn_comment,
        qrcodes,
        reward_btn_enable
    } = hexo.config.bottom_btn.reward_btn || {};

    // 点赞按钮变量,解包操作
    const {
        like_btn_icon,
        like_hover_btn_icon,
        like_btn_text,
        like_btn_enable,
        serverUrl
    } = hexo.config.bottom_btn.like_btn || {};

    const enable = hexo.config.bottom_btn.enable

    if (!enable) {
        return null;
    }

    // 打赏按钮
    const rewardButtonScript = reward_btn_enable
        ? `<script src="/js/reward-button.js"></script>
      <script>
        new RewardButton({
          btnIcon: ${reward_btn_icon ? `"${reward_btn_icon}"` : "null"},
          btnText: "${reward_btn_text}",
          comment: "${reward_btn_comment}",
          qrcodes: ${JSON.stringify(qrcodes)}
        }).init();
      </script>`
        : "";


    // 点赞按钮
    const likeButtonScript = like_btn_enable
        ? `<script src="/js/like-button.js"></script>
        <script>
            new LikeButton({
                btnIcon: "${like_btn_icon}",
                btnHoverIcon: "${like_hover_btn_icon}",
                btnText: "${like_btn_text}",
                serverURL:"${serverUrl}"
            }).init();
        </script>`
        : "";

    return `
    <link defer rel="stylesheet" href="/css/ButtomBtn.css"/>
    ${rewardButtonScript}
    ${likeButtonScript}
    `;

}, "post");

至此,注入器配置完毕

JavaScript

分别写两个JavaScript文件来实现点赞按钮和赞赏按钮的业务功能

赞赏按钮

打开目录themes\fluid\source\js,在下面创建个reward-button.js,将下面代码粘贴进去

注意,如果是采用npm install,即模块安装主题,那要在这个位置node_modules\hexo-theme-fluid\source\js

// 赞赏按钮功能

function RewardButton(config) {
    this.btnIcon = config.btnIcon;
    this.btnText = config.btnText;
    this.comment = config.comment;
    this.qrcodes = config.qrcodes;
}

RewardButton.prototype = {
    init: function () {
        let btnId = "reward-btn";
        let qrcodesId = "reward-qrcodes";

        // 赞赏按钮
        var btn = document.createElement("button");
        btn.id = btnId;
        btn.type = "button";
        btn.innerHTML = `<i class="iconfont ${this.btnIcon}"></i><span>${this.btnText}</span>`;


        // 二维码容器
        var qrcodes = document.createElement("div");
        qrcodes.id = qrcodesId;

        // 按钮容器
        var div = document.createElement("div");
        div.id = "bottomBtn";
        div.style.textAlign = "center";
        div.appendChild(btn);
        div.innerHTML += `<br><br><span class="image-caption">${this.comment}</span>`;
        div.appendChild(qrcodes);

        // 将按钮容器插入在文章后面
        var postNav = document.querySelector(".post-prevnext");
        postNav.parentNode.insertBefore(div, postNav);

        // 按钮点击事件
        document.getElementById(btnId).onclick = function () {
            var container = document.getElementById(qrcodesId);

            if (container.childNodes.length == 0) {
                for (var i = 0; i < this.qrcodes.length; i++) {
                    var qrcode = document.createElement("p");
                    qrcode.className = "reward-qrcode";

                    var img = document.createElement("img");
                    img.src = this.qrcodes[i].src;
                    img.title = this.qrcodes[i].title;
                    img.alt = this.qrcodes[i].title;

                    var caption = document.createElement("p");
                    caption.className = "image-caption";
                    caption.innerText = this.qrcodes[i].caption;

                    qrcode.appendChild(img);
                    qrcode.appendChild(caption);
                    container.appendChild(qrcode);
                }
            } else if (container.style.display == "none") {
                container.style.removeProperty("display");
            } else {
                container.style.display = "none";
            }
        }.bind(this);


    },

};

点赞按钮

定位到位置themes\fluid\source\js,创建个JavaScript文件like-button.js,将下面代码粘贴进去

同上,如果是采用模块安装,那要放在这个位置node_modules\hexo-theme-fluid\source\js

function LikeButton(config) {
    this.btnIcon = config.btnIcon;
    this.btnHoverIcon = config.btnHoverIcon
    this.btnText = config.btnText;
    this.server_url = config.serverURL;
}

LikeButton.prototype = {
    init: function () {
        var likeBtn = this;
        var btn = document.createElement("button");
        btn.id = "like-btn";
        btn.type = "button";
        btn.innerHTML = `<i class="iconfont ${this.btnIcon}"></i><span>${this.btnText}</span>`;
        var objid = null;
        editSpan();

        btn.addEventListener("click", function () {
            // 检查是否已经点过赞,点过忽略
            // var likeStatus = getCookie("likeStatus");
            // if (likeStatus === "liked") {
            //     console.log("您已经点过赞了!");
            //     return;
            // }

            // id 不为空的话,直接修改文本,否则创建对象
            var spanObj = document.querySelector("#like-btn span")
            if (objid) {
                spanObj.innerText = Number(spanObj.innerText) + 1;
                updatePost(objid, spanObj.innerText)
            } else {
                spanObj.innerText = 1;
                createPost()
            }
            // 设置1天cookie
            // setCookie("likeStatus", "liked", 1);

            //修改点赞状态
            try {
                var love_icon = document.querySelector("#like-btn i");
                if (love_icon) {
                    love_icon.classList.remove(likeBtn.btnIcon);
                    love_icon.classList.add(likeBtn.btnHoverIcon);
                }
            } catch (TypeError) {
                console.error("发生异常:", error);
            }
        })

        // 设置 cookie
        function setCookie(name, value, days) {
            var expires = "";
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
                expires = "; expires=" + date.toGMTString();
            }
            // 设置cookie的path为当前页面路径
            var path = window.location.pathname.replace(/\/[^\/]*$/, '');
            document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=" + path;
        }


        // 获取 cookie
        function getCookie(name) {
            var nameEQ = encodeURIComponent(name) + "=";
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i];
                while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length);
                if (cookie.indexOf(nameEQ) == 0) return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length));
            }
            return null;
        }

        function editSpan() {
            /* 
            检测对应网址是否有点赞对象
            有的话显示数量,拿取对应的objid,方便后续点赞操作
            没有的话显示配置文本
            */

            var url = `${likeBtn.server_url}/.netlify/functions/like_count/?action=check`;
            var xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    var targetObj = null;
                    // 检查所有target是否匹配当前页面
                    for (var i = 0; i < data.results.length; i++) {
                        var result = data.results[i];

                        // 数据库采用中文,这里也要解码成中文对比
                        if (result.target === decodeURIComponent(window.location.pathname)) {
                            targetObj = result;
                            break;
                        }
                    }
                    // 如果找到对应对象,显示对应数量;否则使用配置文本
                    if (targetObj) {
                        btn.querySelector("span").innerText = targetObj.count;
                        objid = targetObj.objectId
                    }
                }
            };
            xhr.send();
        }

        function createPost() {
            /* 创建对象 */
            var url = `${likeBtn.server_url}/.netlify/functions/like_count?action=create&pathname=${window.location.pathname}`;
            var xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    objid = JSON.parse(xhr.responseText).objectId
                    console.log(`点赞对象创建成功,${objid}`);
                }
            };
            xhr.send();
        }

        function updatePost(objectId, count) {
            /* 更新对象 */
            var url = `${likeBtn.server_url}/.netlify/functions/like_count?action=update&objectId=${objectId}&count=${count}`

            var xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    console.log('点赞+1');
                    // console.log(xhr.responseText)
                }
            };
            xhr.send();
        }

        // 插入在赞赏按钮后面
        var div = document.querySelector("#reward-btn");
        div.insertAdjacentElement("afterend", btn);
    },
};

至此,JavaScript文件配置完毕

CSS

定位路径themes\fluid\source\css,新建一个Css文件ButtomBtn.css

同上,如果是模块安装,那要放在这个位置node_modules\hexo-theme-fluid\source\css

代码的具体作用均有注释,可以根据实际需求更改

/* 按钮样式 */
#reward-btn,
#like-btn {
    border-radius: 30px;
    padding: 8px 16px;
    background-color: #fff;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    border: none;
    cursor: pointer;
    /* 设置个固定宽度,防止点赞后文本变化,导致按钮自适应缩短 */
    width: 100px;

}

/* 调整两个按钮间距 */
#like-btn {
    margin-left: 15px;
}

/* 按钮图标与文字间隔 */
#like-btn span,
#reward-btn span{
    padding-left: 5px;
    font-size: 15px;
}


/* 图标颜色 */
#like-btn i {
    color: #b24950;
}
#reward-btn i {
    color: #dfc38c;

}

/* 调整图标 */
#like-btn i,
#reward-btn i {
    display: inline-block;
    width: 1.5em;
    height: 20px;
    /* vertical-align: middle; */
}

/* 震动动画效果 */
#like-btn:hover i,
#reward-btn:hover i {
    animation: shake 0.5s;
    /* animation-iteration-count: infinite; */
}


@keyframes shake {

    10%,
    90% {
        transform: translate(-1px, 0);
    }

    20%,
    80% {
        transform: translate(2px, 0);
    }

    30%,
    50%,
    70% {
        transform: translate(-4px, 0);
    }

    40%,
    60% {
        transform: translate(4px, 0);
    }
}


/* 赞赏按钮大小与动画效果等 */
.reward-qrcode {
    display: inline-block;
    margin: 1.5rem !important;
    width: 10rem;
    height: 10rem;
    -webkit-animation: show_qrcodes .3s .1s ease both;
    -moz-animation: show_qrcodes .3s .1s ease both;
    -o-animation: show_qrcodes .3s .1s ease both;
    -ms-animation: show_qrcodes .3s .1s ease both;
    animation: show_qrcodes .3s .1s ease both;
}

.reward-qrcode img {
    margin-top: 0 !important;
}

@-moz-keyframes show_qrcodes {
    0% {
        opacity: 0;
        -webkit-transform: translateY(-10px);
        -moz-transform: translateY(-10px);
        -o-transform: translateY(-10px);
        -ms-transform: translateY(-10px);
        transform: translateY(-10px);
    }

    100% {
        opacity: 1;
        -webkit-transform: translateY(0);
        -moz-transform: translateY(0);
        -o-transform: translateY(0);
        -ms-transform: translateY(0);
        transform: translateY(0);
    }
}

@-webkit-keyframes show_qrcodes {
    0% {
        opacity: 0;
        -webkit-transform: translateY(-10px);
        -moz-transform: translateY(-10px);
        -o-transform: translateY(-10px);
        -ms-transform: translateY(-10px);
        transform: translateY(-10px);
    }

    100% {
        opacity: 1;
        -webkit-transform: translateY(0);
        -moz-transform: translateY(0);
        -o-transform: translateY(0);
        -ms-transform: translateY(0);
        transform: translateY(0);
    }
}

@-o-keyframes show_qrcodes {
    0% {
        opacity: 0;
        -webkit-transform: translateY(-10px);
        -moz-transform: translateY(-10px);
        -o-transform: translateY(-10px);
        -ms-transform: translateY(-10px);
        transform: translateY(-10px);
    }

    100% {
        opacity: 1;
        -webkit-transform: translateY(0);
        -moz-transform: translateY(0);
        -o-transform: translateY(0);
        -ms-transform: translateY(0);
        transform: translateY(0);
    }
}

@keyframes show_qrcodes {
    0% {
        opacity: 0;
        -webkit-transform: translateY(-10px);
        -moz-transform: translateY(-10px);
        -o-transform: translateY(-10px);
        -ms-transform: translateY(-10px);
        transform: translateY(-10px);
    }

    100% {
        opacity: 1;
        -webkit-transform: translateY(0);
        -moz-transform: translateY(0);
        -o-transform: translateY(0);
        -ms-transform: translateY(0);
        transform: translateY(0);
    }
}

至此,按钮样式配置完毕

图标

图标个人采用的是阿里的图标库

先说下怎么添加自定义图标,下面也会提供个人在用的图标

两个方式选择一种即可

自定义图标

先搜索自己要的图标

image-20230415220540996

选择一款中意的加入购物车

image-20230415220627628

挑选完后,点击上方的购物车

image-20230415220707712

点击添加至项目

image-20230415220746477

点击这里,生成一个CDN链接

这里也可以直接使用CDN来使用图标,但因为提示仅供体验和调试

所以下载到自己的项目会比较保险一点,防止404加载不出来

image-20230415220929393

之后点击链接

image-20230415221005439

会打开一个页面,将这里的css代码都复制下来

image-20230415221138991

打开你hexo的站点文件夹,定位到themes\fluid\source\css

如果是使用模块安装的fluid主题,定位到node_modules\hexo-theme-fluid\source\css

新建个travelling.css,或者要可以自己命名

之后返回刚才的页面,选择下载至本地,是一个压缩包,下载后解压出来

image-20230415221528075

打开download文件夹,将里面的文件夹重新命名为icont-font

将这个文件夹放到themes\fluid\source\css位置,如图所示

image-20230415221738335

之后修改下travelling.css,将前面三行url修改下,原先是采用网络,现在改成引用自己项目的资源

原先

@font-face {
  font-family: "iconfont"; /* Project id 4012526 */
  src: url('//at.alicdn.com/t/c/font_4012526_9quof0837i.woff2?t=1681567787526') format('woff2'),
       url('//at.alicdn.com/t/c/font_4012526_9quof0837i.woff?t=1681567787526') format('woff'),
       url('//at.alicdn.com/t/c/font_4012526_9quof0837i.ttf?t=1681567787526') format('truetype');
}

修改后

@font-face {
    font-family: "iconfont";
    /* Project id 4012526 */
    src: url('icont-font/iconfont.woff2') format('woff2'),
        url('icont-font/iconfont.woff') format('woff'),
        url('icont-font/iconfont.ttf') format('truetype');
}

博主使用

如果不自定义,也可以通过这个阿里云链接下载到目前个人在用的点赞和赞赏图标

直接放在themes\fluid\source\css位置下

然后创建个travelling.css,将下面代码粘贴进去保存即可

@font-face {
    font-family: "iconfont";
    /* Project id 4012526 */
    src: url('icont-font/iconfont.woff2') format('woff2'),
        url('icont-font/iconfont.woff') format('woff'),
        url('icont-font/iconfont.ttf') format('truetype');
}

.iconfont {
    font-family: "iconfont" !important;
    font-size: 16px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.icon-yue1:before {
    content: "\e665";
}

.icon-money:before {
    content: "\e62e";
}

.icon-l-money:before {
    content: "\e79c";
}

.icon-uf_money:before {
    content: "\e62f";
}

.icon-money1:before {
    content: "\e612";
}

.icon-moneycollect:before {
    content: "\e7cd";
}

.icon-icon_love_hover:before {
    content: "\e69c";
}

.icon-icon_love:before {
    content: "\e69d";
}

.icon-money-funds:before {
    content: "\e831";
}

.icon-huochecheci:before {
    content: "\e685";
}

配置

下载完文件后,接下来要配置下配置文件

打开站点配置文件config.yml

将点赞和赞赏的图标类名分别写入like_btn_iconreward_btn_icon

例如:

image-20230415222521700

  • 点赞的图标名字是icon-icon_love,那就在like_btn_icon填入iconfont reward_btn_icon
  • 点赞后的图标名字是icon-icon_love_hover,那就在like_hover_btn_icon填入icon-icon_love_hover
  • 赞赏的图标名字是reward_btn_icon,那就在reward_btn_icon填写:iconfont reward_btn_icon

自定义图标的,填写自己挑选的图标的名字即可,参照博主的,使用我的文件的,直接使用下面的名字即可

bottom_btn:
  enable: true
  reward_btn:
    # 打赏按钮
    reward_btn_enable: true
    reward_btn_icon: iconfont icon-money
    reward_btn_text: 打赏
    reward_btn_comment: "如果觉得本文对你有所帮助,请打赏——1元就足够感动我😘"
    qrcodes:
      - src: /images/wechatpay.jpg
        caption: 微信
        title: 微信赞赏码
      - src: /images/zhifubaopay.jpg
        caption: 支付宝
        title: 支付宝收款码
  like_btn:
    # 点赞按钮
    like_btn_enable: true
    like_btn_icon: icon-icon_love
    like_hover_btn_icon: icon-icon_love_hover
    like_btn_text: 点赞
    leancloud_id: 
    leancloud_key: 
    serverUrl: 

至此,图标配置完毕

数据库

这里使用国际版或者国内版都可以

创建应用

已有应用可以忽略这一步

登录,点击左上角按钮,进入应用页面

image-20230415214956207

点击按钮,创建个leancloud的应用

image-20230415215029608

随便起个名字,确定即可

image-20230415215117429

点击新建应用的数据存储,进入应用

image-20230415215235956

新建类

新建个Like

image-20230415215341146

image-20230415215531291

密钥

接下里要获取下密钥信息,用于config配置文件

点击按钮,打开侧边栏

image-20230415215629375

选择设置-应用凭证

image-20230415215727865

将这里的信息填入config.yml对应的位置

这里说下,我这个是Demo应用,过后就删除了,所以不用特意去记我的密钥,没用

image-20230415215824397

配置

打开config.yml文件,将上面得到的信息填入

  • AppID填入leancloud_key
  • MasterKey填入leancloud_key

注:这里的leancloud_key必须采用MasterKey,而不是AppKey

bottom_btn:
  enable: true
  reward_btn:
    # 打赏按钮
    reward_btn_enable: true
    reward_btn_icon: iconfont icon-money
    reward_btn_text: 打赏
    reward_btn_comment: "如果觉得本文对你有所帮助,请打赏——1元就足够感动我😘"
    qrcodes:
      - src: /images/wechatpay.jpg
        caption: 微信
        title: 微信赞赏码
      - src: /images/zhifubaopay.jpg
        caption: 支付宝
        title: 支付宝收款码
  like_btn:
    # 点赞按钮
    like_btn_enable: true
    like_btn_icon: iconfont icon-icon_love
    like_btn_text: 点赞
    leancloud_id: RQMd3w90p14fUiKvMsLEjUdk-gzGzoHsz
    leancloud_key: NHKmK8zO9lZaMLHWmoJuGRNc
    serverUrl: 

至此,数据库配置完毕

云函数

这里讲下,因为我们要使用到leancloud作为数据库,要使用到API

KEYID是不能直接写在客户端(JavaScript),否则人家调试,可以直接拿到KEYID,能间接操作你的数据库

所以要将KEYID或者说API相关的操作放在服务端

由于个人只有本地服务器,没有云服务器,所以只能白嫖Netlify的云函数来跑

如果有云服务器,可以专门放个端口专门跑这个代码,给外部提供个接口

由于我没有云服务器可以实践,所以给不了具体的指导,想使用自己云服务器的也可以自己琢磨下

Netlify云函数这块其实也不懂,参考文档,琢磨文档

只能说能用,但不懂🙃,也就刚好能运行云函数,能跑就行~

安装模块

具体来说,先创建个文件夹Netlify_func,命名随意不影响

cmd进入这个文件,安装下NetlifyCLI模块

npm install netlify-cli -g

登录授权

运行以下命令,进行身份验证和获取访问令牌

image-20230415211145924

netlify login

杀毒软件有通知的话,放行下

image-20230415211130975

这将打开一个浏览器窗口,要求您使用 Netlify 登录并授予对Netlify CLI 的访问权限,直接选择同意即可

image-20230415211214825

点击后,如图所示,提示已经授权,关闭页面即可

image-20230415211237652

获得授权后,Netlify CLI 会将您的访问令牌存储在config.json全局配置文件中。

具体的位置:

  • 苹果系统:Library/Preferences/netlify/config.json
  • Linux:.config/netlify/config.json
  • window:AppData\Roaming\netlify\Config\config.json

建立站点

运行命令

netlify init

会询问你是要绑定仓库,还是建立一个没有的git的站点,这里个人暂时没有使用git

所以先选择第一个,yes

这里的步骤,也可以先写本地云函数脚本,然后git推送到远程仓库

然后使用第二个绑定远程的仓库,都行,看个人具体操作

image-20230415210933396

英文翻译过来的意思

No git remote was found, would you like to set one up?
It is recommended that you initialize a site that has a remote repository in GitHub.
This will allow for Netlify Continuous deployment to build branch & PR previews.
For more details on Netlify CI checkout the docs: http://bit.ly/2N0Jhy5
? Do you want to create a Netlify site without a git repository? (Use arrow keys)

找不到git遥控器,你想设置一个吗?
建议您初始化在GitHub中具有远程存储库的站点。
这将允许Netlify连续部署来构建分支机构和PR预览。
有关Netlify CI签出文档的更多详细信息:http://bit.ly/2N0Jhy5
? 您想创建一个没有git存储库的Netlify网站吗?(使用箭头键)

会询问你选择哪个团队Team,如果只有一个,回车就是

image-20230415211931269

再接着,让你给站点项目起个名字,直接回车的话随机命名,随意,个人直接回车

image-20230415211959564

创建后的提示(该站点总结完笔记个人会删除,所以不用测试链接了)

image-20230415212057305

这里第二个地址,就是我们配置文件要填写的云函数地址serverUrl

当然现在只是建立了站点,云函数功能还没实现

打开Netlify的站点,也可以发现创建了一个站点

Netlify网址:官网,方便打开

image-20230415212351061

不过,点进去,可以发现暂时是没有云函数的

image-20230415212551978

创建函数

接下来就是创建云函数和部署到站点

在这个云函数文件夹根目录(也就是我上面创建的Netlify_func),使用cmd进入

运行命令:netlify functions:create

先让Netlify创建个示例文件,等下直接修改就行

第1步问你,采用什么云函数,选择第二个Serverless即可

image-20230415213203903

第2步问你,采用什么语言,选择JavaScript

image-20230415213301129

第3步问题,采用什么模板文件,选择auth-fetch即可(无关紧要,后面要修改)

image-20230415213348196

第4步,给项目起个名字,这里输入一个项目名字即可,我这里输入like_count

image-20230415213526778

创建后的文件结构,如图所示

Demo
 ├── .gitignore
 ├── .netlify
 │   └── state.json
 └── netlify
     └── functions
         └── like_count
             ├── like_count.js
             ├── node_modules
             ├── package-lock.json
             └── package.json

先在functions文件夹下新建一个config.js用于存储我们的KeyID
将自己leancloudIDKey填写进去

注:这里的IDKEY个人仅做Demo演示,后续会删除应用

module.exports = {
  LC_APP_ID: 'RQMd3w90p14fUiKvMsLEjUdk-gzGzoHsz',
  LC_APP_KEY: 'NHKmK8zO9lZaMLHWmoJuGRNc',
};

打开like_count.js文件,将代码全部清空,将以下全部代码复制粘贴进去,不用进行任何修改

这里主要是3个函数,对leancloud数据库的操作(更新对象、查询对象、创建对象)

const fetch = require('node-fetch');
const config = require('./config');

const responseHeaders = {
  'Access-Control-Allow-Origin': 'http://localhost:4000',
  'Access-Control-Allow-Methods': 'GET',
  'Access-Control-Allow-Methods': 'POST',
  'Access-Control-Allow-Headers': 'Content-Type',
};

const checkLikeCount = async function () {
  const url = 'https://bfrlyu2d.lc-cn-n1-shared.com/1.1/classes/Like';
  const headers = {
    'Content-Type': 'application/json',
    'X-LC-Id': config.LC_APP_ID,
    'X-LC-Key': config.LC_APP_KEY,
  };
  try {
    const response = await fetch(url, { headers });
    if (!response.ok) {
      // NOT res.status >= 200 && res.status < 300
      return { statusCode: response.status, body: response.statusText };
    }
    const data = await response.json();

    return {
      statusCode: 200,
      headers: responseHeaders,
      body: JSON.stringify(data),
    };
  } catch (error) {
    console.log(error);
    return {
      statusCode: 500,
      headers: responseHeaders,
      body: JSON.stringify({ msg: error.message }),
    };
  }
};

const createLikeCount = async function (pathname) {
  console.log('run create')
  const url = 'https://bfrlyu2d.lc-cn-n1-shared.com/1.1/classes/Like'
  const headers = {
    'Content-Type': 'application/json',
    'X-LC-Id': config.LC_APP_ID,
    'X-LC-Key': config.LC_APP_KEY,
  }
  try {
    const response = await fetch(url, {
      headers,
      method: 'POST',
      body: JSON.stringify({
        count: 1,
        target: pathname,
      }),
    })
    if (!response.ok) {
      // NOT res.status >= 200 && res.status < 300
      return { statusCode: response.status, body: response.statusText }
    }
    const data = await response.json()

    return {
      statusCode: 200,
      headers: responseHeaders,
      body: JSON.stringify(data),
    }
  } catch (error) {
    console.log(error)
    return {
      statusCode: 500,
      headers: responseHeaders,
      body: JSON.stringify({ msg: error.message }),
    }
  }
}

const updateLikeCount = async function (objectId, count) {
  const url = `https://bfrlyu2d.lc-cn-n1-shared.com/1.1/classes/Like/${objectId}`;
  const headers = {
    'Content-Type': 'application/json',
    'X-LC-Id': config.LC_APP_ID,
    'X-LC-Key': config.LC_APP_KEY,
  };
  try {
    const response = await fetch(url, {
      headers,
      method: 'PUT',
      body: JSON.stringify({ count: Number(count) }),
    });
    if (!response.ok) {
      // NOT res.status >= 200 && res.status < 300
      return { statusCode: response.status, body: response.statusText };
    }
    const data = await response.json();

    return {
      statusCode: 200,
      headers: responseHeaders,
      body: JSON.stringify(data),
    };
  } catch (error) {
    console.log(error);
    return {
      statusCode: 500,
      headers: responseHeaders,
      body: JSON.stringify({ msg: error.message }),
    };
  }
};

const myFunction = async function (event, context) {
  if (event && event.queryStringParameters && event.queryStringParameters.action === 'check') {
    return await checkLikeCount();
  } else if (
    event &&
    event.queryStringParameters &&
    event.queryStringParameters.action === 'update' &&
    event.queryStringParameters.objectId &&
    event.queryStringParameters.count
  ) {
    const objectId = event.queryStringParameters.objectId;
    const count = event.queryStringParameters.count;
    return await updateLikeCount(objectId, count);
  } else if (
    event &&
    event.queryStringParameters &&
    event.queryStringParameters.action === 'create' &&
    event.queryStringParameters.pathname
  ) {
    const target = event.queryStringParameters.pathname;
    return await createLikeCount(target);
  }
};


exports.handler = async (event, context) => {
  return await myFunction(event, context);
};

部署

在根目录下运行cmd,执行部署命令:netlify deploy --prod

如果是只在文件夹局部安装模块,采用npx netlify deploy --prod

如果上面跟我一致的话,就直接运行netlify deploy --prod即可

会询问你发布的目录,这里直接回车即可(也就是将当前目录都发布到站点上去)

image-20230415214547498

稍微等一下,会部署到站点,部署后如图所示

image-20230415214702581

配置

将上面部署后,得到的提示信息中的Website URL填入config.yml即可

打开config.yml,将网址填入serverUrl

bottom_btn:
  enable: true
  reward_btn:
    # 打赏按钮
    reward_btn_enable: true
    reward_btn_icon: iconfont icon-money
    reward_btn_text: 打赏
    reward_btn_comment: "如果觉得本文对你有所帮助,请打赏——1元就足够感动我😘"
    qrcodes:
      - src: /images/wechatpay.jpg
        caption: 微信
        title: 微信赞赏码
      - src: /images/zhifubaopay.jpg
        caption: 支付宝
        title: 支付宝收款码
  like_btn:
    # 点赞按钮
    like_btn_enable: true
    like_btn_icon: iconfont icon-icon_love
    like_btn_text: 点赞
    leancloud_id: RQMd3w90p14fUiKvMsLEjUdk-gzGzoHsz
    leancloud_key: NHKmK8zO9lZaMLHWmoJuGRNc
    serverUrl: https://delightful-marshmallow-761733.netlify.app

至此,云函数部署完成

后话

至此,全部config.yml均已配置完成

之后Hexo运行三件套,应该就能看到效果了

  • hexo clean
  • hexo g
  • hexo s

如果期间有遇到问题,也欢迎给我留言咨询~