借助云开发搭建专属技术博客小程序丨实战

  • 2019 年 12 月 26 日
  • 筆記

▌导语

一直对小程序开发很感兴趣,之前就准备做一款属于自己的小程序,无奈还需要购买云服务器和部署后台,有点麻烦,自从知道有了云开发这个免去服务器搭建和运维的一站式后端云服务“神器”,就一鼓作气花了几个周末的时间做了一款自己的博客小程序,如果你也想打造一款自己的博客,那你阅读这篇文章就够啦。

▌博客小程序介绍

主要功能:

包括文章的发布及浏览、评论、点赞、浏览历史、分类、排行榜、分享、生成海报图等。

效果展示:

▌数据库设计

数据库主要就7张表,分别为:用户表,分类表,文章表,文章内容表,评论表,点赞表,历史浏览表。

▌评论功能设计

以文章评论功能为例,我们来看看代码以及小程序云开发的整个流程。

1. 实现思路

一开始的实现思路是准备搞两张表,一张评论主表,一张回复评论的子表,后来想着不用这么复杂,其实就用一张表也能实现评论及回复的功能。

2. 代码实现

发表评论有三种情况,第一种是评论文章,为一级评论,第二种是评论别人的评论,为二级评论,第三种是回复别人的评论,为三级评论。

2.1 如何新增一条评论

结合上面图片,我们再来看看代码,就很清晰了。

/**     * 发布评论     */  submit() {      var comment = this.data.inputData      if (comment == '') {        wx.showToast({          title: '请填写评论',          icon: 'none'        })      } else {        console.log("我的评论:" + this.data.inputData)        var type = this.data.type;        if (type == 1) { // 1是评论别人的评论》二级评论          this.replyComment(1)        } else if (type == 2) {          this.replyComment(2) // 2是回复别人的评论》三级评论        } else if (type == 3) { // 3是评论文章》一级评论          this.addComment();        }      }    },     /**     * 新增评论     */    addComment() {      var _this = this;      var openid = wx.getStorageSync("openid")      wx.showLoading({        title: '正在加载...',      })      var create_date = util.formatTime(new Date());      console.log("当前时间为:" + create_date);      var timestamp = Date.parse(new Date());      timestamp = timestamp / 1000;      console.log("当前时间戳为:" + timestamp);      // 调用云函数      wx.cloud.callFunction({        name: 'addComment',        data: {          //_id: timestamp + _this.data.otherUserInfo._id,          id: _this.data.articleDetail._id,          _openid: openid,          avatarUrl: _this.data.userInfo.avatarUrl,          nickName: _this.data.userInfo.nickName,          comment: _this.data.inputData,          create_date: create_date,          flag: 0,          article_id: _this.data.articleDetail.article_id,          timestamp: timestamp,          childComment: [],        },        success: res => {          // res.data 包含该记录的数据          console.log("新增评论成功---")          wx.showToast({            title: '评论提交成功',            })          wx.navigateBack({            delta: 1          })        },        fail: err => {          console.error('[云函数]调用失败', err)        },        complete: res => {          wx.hideLoading()        }      })    },    /**     * 回复评论     */    replyComment(commentType) {      var _this = this;      wx.showLoading({        title: '正在加载...',      })      var create_date = util.formatTime(new Date());      console.log("当前时间为:" + create_date);      var timestamp = Date.parse(new Date());      timestamp = timestamp / 1000;      wx.cloud.callFunction({        name: 'replyComment',        data: {          id: _this.data.articleDetail._id,          _id: _this.data.otherUserInfo._id,          avatarUrl: _this.data.userInfo.avatarUrl,          nickName: _this.data.userInfo.nickName,          openId: _this.data.openid,          comment: _this.data.inputData,          createDate: create_date,          flag: commentType,          opposite_avatarUrl: _this.data.otherUserInfo.avatarUrl,          opposite_nickName: _this.data.otherUserInfo.nickName,          opposite_openId: _this.data.otherUserInfo._openid,          timestamp: timestamp,        },        success: res => {          // res.data 包含该记录的数据          console.log("回复评论成功---")          wx.showToast({            title: '回复提交成功',          })          wx.navigateBack({            delta: 1          })        },        fail: err => {          console.error('[云函数]调用失败', err)        },        complete: res => {          wx.hideLoading()        }      })    },

下面是新增评论和回复评论的两个云函数,主要用到了async和await这两个函数,让新增和回复函数执行完后我们再更新一下article文章表的评论字段,让其加1,async和await的好处就是可以让函数有序的进行,这里就不赘述。

// 新增评论云函数  const cloud = require('wx-server-sdk')  var env = 'hsf-blog-product-xxxxx'; // 正式环境  // var env = 'xxxxxxxxxxxxx'; // 测试环境  cloud.init({    env: env  })  const db = cloud.database()  const _ = db.command  exports.main = async(event, context) => {    try {      let res = await db.collection('comment').add({        data: {          _openid: event._openid,          avatarUrl: event.avatarUrl,          nickName: event.nickName,          comment: event.comment,          create_date: event.create_date,          flag: event.flag,          article_id: event.article_id,          timestamp: event.timestamp,          childComment: [],        }      }).then(res => {        return res;      })      await db.collection('article').doc(event.id).update({        data: {          comment_count: _.inc(1)        }      })      return res;    } catch (e) {      console.error(e)    }  }
// 回复评论云函数  const cloud = require('wx-server-sdk')  var env = 'hsf-blog-product-xxxxx';  // 正式环境  // var env = 'xxxxxxxxxxxxxx'; // 测试环境  cloud.init({    env: env  })  const db = cloud.database()  const _ = db.command  exports.main = async(event, context) => {    try {      let res = await db.collection('comment').doc(event._id).update({        data: {          childComment: _.push({            avatarUrl: event.avatarUrl,            nickName: event.nickName,            openId: event.openId,            comment: event.comment,            createDate: event.createDate,            flag: event.flag,            opposite_avatarUrl: event.opposite_avatarUrl,            opposite_nickName: event.opposite_nickName,            opposite_openId: event.opposite_openId,            timestamp: event.timestamp,          })        }      }).then(res => {        return res;      })      await db.collection('article').doc(event.id).update({        data: {          comment_count: _.inc(1)        }      })      return res;    } catch (e) {      console.error(e)    }  }

2.2 如何显示每一条评论

从数据库取出评论的数据,循环遍历每一条父评论,如果有子回复也一并循环。这里每一条评论的唯一标识是用户的openId,那么我们可以用这个做一些事情,如:可以判断如果是自己的评论是不能回复的。

<view class="comment" wx:if="{{commentList.length>0}}">        <view class="comment-line">          <text class="comment-text">评论交流</text>          <view class="bottom-line"></view>        </view>        <block wx:for='{{commentList}}' wx:key='*this' wx:for-item="itemfather">          <view class='commentList'>            <view class="top-info">              <view class='img-name'>                <image src="{{itemfather.avatarUrl}}"></image>                <label>{{itemfather.nickName}}</label>              </view>            </view>            <view class="father-content">              <text class="text">{{itemfather.comment}}</text>              <view class="father-reply-time">                <text class="create-time">{{itemfather.create_date}}</text>                <text class="reply" data-item="{{itemfather}}" bindtap='clickFatherConter' wx:if="{{openid != itemfather._openid}}">回复</text>              </view>            </view>            <view class="children-content">              <block wx:for='{{itemfather.childComment}}' wx:key='*this'>                <view class='childComment'>                  <view class="child-img-name">                    <view class="avatar-name">                      <image src="{{item.avatarUrl}}"></image>                      <text class='nickName'>{{item.nickName}}</text>                    </view>                  </view>                  <view class="child-comment" wx:if="{{item.flag==2 }}">                    <text class='huifu'>回复</text>                    <text class='opposite-nickName'>{{item.opposite_nickName}}</text>                    <text class='comment-text'>{{item.comment}}</text>                  </view>                  <view class="child-comment" wx:if="{{item.flag==1}}">                    <text class='comment-text'>{{item.comment}}</text>                  </view>                  <view class="child-reply-time">                    <text class="child-create-time">{{item.createDate}}</text>                    <text class="reply" data-item="{{item}}" data-id="{{itemfather._id}}" bindtap='clickChildrenConter' wx:if="{{openid != item.openId}}">回复</text>                  </view>                </view>              </block>            </view>          </view>        </block>      </view>

▌项目运行

1. 下载源码

在github上将代码下载到本地:

https://github.com/husanfeng/hsf_blog.git

2. 环境准备

(1)下载小程序开发工具;

(2)注册appid;

(3)使用小程序开发工具导入下载的代码,填入自己注册的AppID。

3. 云开发准备

(1)开通云开发功能。

(2)创建测试环境和生产环境。

4. 修改环境ID

(1)修改app.js中的环境ID为自己的环境ID。

(2)修改所有云函数中的环境ID为自己的环境ID。

5. 云函数部署

(1)右键云函数目录,点击在终端中打开,执行npm install。

(2)右键执行上传并部署:所有文件。

6. 构建npm

(1)勾选使用npm模块。

(2)点击顶部功能栏,执行构建npm。

7. 执行编译

▌发布注意事项

小程序现在审核也是越来越严谨了,为了不让大家在审核道路上走弯路,我把我的一些经验分享给大家。

  1. 在微信公众平台上为小程序选择正确恰当的服务类目,例如博客类的小程序就可以选择教育信息服务。
  2. 如果你的小程序需要账号密码登录,提交审核时需要提交一个账号和密码,而且这个账号不能是测试账号,不能出现测试数据。
  3. 提交审核的版本首页需要有数据展示,例如:博客小程序你需要发布一篇或者多篇文章。
  4. 文章内容不能存在敏感内容。
  5. 评论功能审核比较严格了,一旦评论中存在敏感词汇,肯定审核不通过,官方建议调用小程序内容安全API,或使用其他技术、人工审核手段,过滤色情、违法等有害信息,保障发布内容的安全。源码地址https://github.com/TencentCloudBase/Good-practice-tutorial-recommended

如果你想要了解更多关于云开发CloudBase相关的技术故事/技术实战经验,请扫码关注【腾讯云云开发】公众号~