2021-07-06

微信小程序云开发实现多用户评论点赞收藏功能

    在微信小程序开发过程中,很多时候有这样的需求,如购物评价商品,收藏商品,给商品点赞等,本文做一个小demo给大家实现。

1.页面效果图如下

下图为一个课程列表页,点击某个课程可实现跳转到课程详情页
在这里插入图片描述
下图为课程详情页,页面展示不太美观,有需求可自己修改样式,详情页包括课程相关信息以及评论区域,重点为评论区域,评论区域包括发送评论,以及对评论进行点赞,显示评论时间等,评论按点赞数目多少从上到下排列。
在这里插入图片描述

2.实现过程

(1)课程列表courses实现代码如下:

//courses.wxml
<block wx:for="{{courseList}}" wx:key="index">
  <view class="itemRoot" bindtap="goCourseDetail" data-id="{{item._id}}">
    <text>{{item.course_name}}</text>
    <text>{{item.course_desc}}</text>
  </view>
</block>

//courses.wxss
.itemRoot{
  border-bottom:1px solid gainsboro;
  margin: 15rpx;
}

//courses.js
Page({
  data: {
    courseList: []
  },
  onLoad: function (options) {
    wx.cloud.database().collection('courseList').get()
      .then(res => {
        console.log("获取成功", res)
        this.setData({
          courseList: res.data
        })
      }).catch(err => {
        console.log("获取失败", err)
      })
  },
  //跳转到详情页
  goCourseDetail(e) {
    wx.navigateTo({
      url: '../course_detail/courses_detail?id=' + e.currentTarget.dataset.id,
    })
  },
})

(2)课程详情页course_detail实现代码如下:

//course_detail.wxml
<!--标题和描述-->
<view>
  <image class="sourseImg" src="../../images/sourse.png"></image>
  <view class="sourseInfo">
    <view class="sourceName">{{course_detail.course_name}}</view>
    <view class="desc">{{course_detail.course_desc}}</view>
  </view>
</view>
<!--评论-->
<view class="tip">评论区域</view>
<block wx:for="{{pinglun}}" wx:key="index">
  <view class="pinglun">
    <image class="touxiang" src="{{item.touxiang}}"></image>
    <view class="pinglin_text">
      <text class="studentName">{{item.studentName}}:</text>
      <view class="content">{{item.content}}</view>
      <view class="dianzantubiao" bindtap="commentDianzan"  data-index="{{index}}">
        
        <image wx:if="{{item.comIsIncloudMan&&userInfo}}"  src="../../images/dianzan-yes.png"  mode="widthFix"></image>
        
        <image wx:if="{{!userInfo||!item.comIsIncloudMan}}" src="../../images/dianzan-no.png"  mode="widthFix"></image>

        <view class="dianzanNum" wx:if="{{item.dianzanMan.length>0}}">{{item.dianzanMan.length}}</view>
      </view>
    </view>
  </view>
  <view class="pinglun_time">{{item.time}}</view>
</block>
<!--发表评论-->
<input class="input" bindinput="getContent" placeholder="请留下您精彩点评吧" value="{{content}}"></input>
<button type="primary" bindtap="publishComment">发表评论</button>

//course_detail.wxss
image {
  width: 100rpx;
  height: 100rpx;
}
.tip {
  margin-top: 30rpx;
  font-size: 50rpx;
  color: goldenrod;
}
.pinglun {
  border-bottom: 2rpx solid gainsboro;
  margin-left: 50rpx;
  margin-top: 50rpx;
  display: flex;
  justify-content: left;
  align-items: center;
}
.input {
  border: 1rpx solid gainsboro;
  margin-top: 150rpx;
  margin-bottom: 60rpx;
}
.sourseImg {
  width: 400rpx;
  height: 400rpx;
}
.sourseInfo {
  display: flex;
  justify-content: space-between
}
.desc {
  padding-right: 40rpx;
}
.sourceName {
  padding-left: 40rpx;
}
.touxiang {
  border-radius: 50%;
  overflow: hidden;
  width: 85rpx;
  height: 85rpx;
}
.studentName {
  padding-left: 10rpx;
}
.content {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.pinglin_text {
  display: flex;
  justify-content: left;
  align-items: center;
  flex: 5;
}
.pinglun_time {
  font-size: 25rpx;
  color: coral;
  text-align: right;
  padding-right: 30rpx;
}
.dianzantubiao{
  display: flex;
  flex-direction: row;
  justify-content: right;
  align-items: right;
}
.dianzantubiao image{
  size: 20rpx;
  width: 55rpx;
}
.dianzanNum{
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 6rpx;
  float: right;
}
course_detail.js代码如下:
let ID = ''
let dianzan = false
Page({
  data: {
    course_detail: '',
    //shoucangUrl: "../../images/shoucang-no.png",
    dianzanUrl: "../../images/dianzan-no.png",
    pinglun: [],
    pingfen: [],
    content: '',
    userInfo: [],
    dianzanStatus: false,
    dianzanNum: 0,
    comIsIncloudMan: false,
    ID: '',
    isIncloudStudentInpingfen:0
  },
  //点击点赞
  clickDianZan() {
    let that = this
    that.authPublic()
    this.setData({
      dianzanUrl: dianzan ? "../../images/dianzan-no.png" : "../../images/dianzan-yes.png"
    })
    dianzan = !dianzan

    wx.cloud.callFunction({
      name: "commentPlus",
      data: {
        action: "dianzan",
        id: ID,
        dianzan: dianzan
      }
    }).then(res => {
      console.log("改变点赞状态成功", res)
    }).catch(err => {
      console.log("改变点赞状态失败", err)
    })
  },


  onShow: function () {
    

  },

  onLoad: function (options) {
    let deleteDoublePage=options.deleteDoublePage
    console.log(deleteDoublePage)
    if(deleteDoublePage==1){
      wx.navigateBack({ //返回
        delta: 1
        });
    }
    ID = options.id
    console.log(ID)
    this.setData({
      ID: ID
    })

    //根据课程ID获取课程详情
    wx.cloud.callFunction({
      name: "commentPlus",
      data: {
        action: "getCourseDetailById",
        id: ID,
      }
    }).then(res => {
      console.log("根据课程ID获取课程详情成功", res)
      let pinglun=res.result.data.pinglun
      //pinglun: 1 8 4 0 2 5
      for(var i=0;i<pinglun.length-1;i++){
        for(var j=i+1;j<pinglun.length;j++){
          if(pinglun[i].dianzanMan.length<pinglun[j].dianzanMan.length){
            let tmp=pinglun[i]
            pinglun[i]=pinglun[j]
            pinglun[j]=tmp
          }
        }
      }
      console.log("hahahaahahhahhahh")
      console.log(pinglun)
      console.log("hahahaahahhahhahh")
      wx.setStorageSync('pingfen', res.result.data.pingfen)
      wx.setStorageSync('pinglun', res.result.data.pinglun)
      this.setData({
        course_detail: res.result.data,
        pinglun: res.result.data.pinglun,
        pingfen: res.result.data.pingfen
      })
      let userInfo = wx.getStorageSync('userInfo')
    this.setData({
      userInfo: userInfo
    })
    let studentName = userInfo.nickName
    ///let pinglun = wx.getStorageSync('pinglun')
    if (studentName) {
      for (var i = 0; i < pinglun.length; i++) {
        if (pinglun[i].dianzanMan.indexOf(studentName) === -1) {
          pinglun[i].comIsIncloudMan = false
        } else {
          pinglun[i].comIsIncloudMan = true
        }
      }
      //wx.setStorageSync('pinglun', pinglun)
      this.setData({
        pinglun: pinglun
      })

      wx.cloud.callFunction({
        name: "commentPlus",
        data: {
          action: "pinglun",
          id: ID,
          pinglun: pinglun
        }
      }).then(res => {
        console.log("改变点赞状态成功", res)
      }).catch(err => {
        console.log("改变点赞状态失败", err)
      })
    }
    }).catch(err => {
      console.log("根据课程ID获取课程详情失败", err)
    })
  },



  //获取学生输入的评论内容
  getContent(e) {
    this.setData({
      content: e.detail.value
    })
  },

  //发表评论
  publishComment() {
    let userInfo = wx.getStorageSync('userInfo')
    let that = this
    //判断评论是否太短
    if (!userInfo) {
      that.authPublic()
    } else {
      let content = this.data.content
      if (content.length < 4) {
        wx.showToast({
          title: '评论太短了',
          icon: "none"
        })
        return
      }
      let pinglunItem = {}
      //获取当前时间
      let time = ''
      var timestamp = Date.parse(new Date());
      var date = new Date(timestamp);
      //获取年  
      var Y = date.getFullYear();
      //获取月  
      var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
      //获取当日 
      var D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
      time = Y + '-' + M + '-' + D
      console.log(time)
      let dianzanStatus = false
      pinglunItem.studentName = userInfo.nickName
      pinglunItem.content = content
      pinglunItem.touxiang = userInfo.avatarUrl
      pinglunItem.time = time
      pinglunItem.dianzanStatus = dianzanStatus
      pinglunItem.dianzanNum = 0
      pinglunItem.dianzanMan = []
      pinglunItem.comIsIncloudMan = false
      let pinglunArr = this.data.pinglun
      pinglunArr.push(pinglunItem)
      console.log("发表后的评论数组", pinglunArr)
      wx.showLoading({
        title: '发表中。。。',
      })
      wx.cloud.callFunction({
        name: "commentPlus",
        data: {
          action: "pinglun",
          id: ID,
          pinglun: pinglunArr
        }
      }).then(res => {
        console.log("评论成功", res)
        wx.setStorageSync('pinglun', pinglunArr)
        this.setData({
          pinglun: pinglunArr,
          content: ''
        })
        wx.hideLoading()
      }).catch(err => {
        console.log("评论失败", err)
        wx.hideLoading()
      })
    }
  },


  //用户授权
  authPublic() {
    let userInfo = wx.getStorageSync('userInfo')
    if (!userInfo) {
      wx.getUserProfile({
        desc: '获取你的昵称、头像、地区及性别',
        success: (res) => {
          //把用户信息缓存到本地
          let userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo
          })
          let studentName = userInfo.nickName
          wx.setStorageSync('userInfo', userInfo)
          let pinglun = wx.getStorageSync('pinglun')

          for (var i = 0; i < pinglun.length; i++) {
            //for (var j = 0; j < pinglun[i].dianzanMan.length; j++) {
            if (pinglun[i].dianzanMan.indexOf(studentName) === -1) {
              console.log(i)
              pinglun[i].comIsIncloudMan = false
            } else {
              console.log("1111", i)
              pinglun[i].comIsIncloudMan = true
              // }
            }
          }
          wx.setStorageSync('pinglun', pinglun)
          this.setData({
            pinglun: pinglun
          })

          wx.cloud.callFunction({
            name: "commentPlus",
            data: {
              action: "pinglun",
              id: ID,
              pinglun: pinglun
            }
          }).then(res => {
            console.log("改变点赞状态成功", res)
          }).catch(err => {
            console.log("改变点赞状态失败", err)
          })

        }, fail: (error) => {
          console.log(error)
        }
      })
    }
  },


  //点击点赞图标
  commentDianzan(e) {
    //判断是否授权
    let userInfo = wx.getStorageSync('userInfo')
    let that = this
    if (!userInfo) {
      that.authPublic()
    } else {
      let userInfo = wx.getStorageSync('userInfo')
      //index表示当前点赞评论的数组坐标
      let index = e.currentTarget.dataset.index
      //1 获取缓存中的评论数组
      let pinglun = wx.getStorageSync("pinglun") || [];

      let studentName = userInfo.nickName
      if (pinglun[index].comIsIncloudMan == true) {
        for (var i = 0; i < pinglun[index].dianzanMan.length; i++) {
          if (pinglun[index].dianzanMan[i] == studentName) {
            pinglun[index].dianzanMan.splice(i, 1)
          }
        }
      }
      if (pinglun[index].comIsIncloudMan == false) {
        pinglun[index].dianzanMan.push(studentName)
        pinglun[index].comIsIncloudMan = true
      }

      console.log("点赞后的评论数组为:", pinglun)
      for (var i = 0; i < pinglun.length; i++) {
        //for (var j = 0; j < pinglun[i].dianzanMan.length; j++) {
        if (pinglun[i].dianzanMan.indexOf(studentName) === -1) {
          pinglun[i].comIsIncloudMan = false
        } else {
          pinglun[i].comIsIncloudMan = true
          // }
        }
      }
      this.setData({
        //dianzanStatus: !dianzanStatus,
        pinglun: pinglun
      });
      wx.setStorageSync('pinglun', pinglun)

      wx.cloud.callFunction({
        name: "commentPlus",
        data: {
          action: "pinglun",
          id: ID,
          pinglun: pinglun
        }
      }).then(res => {
        console.log("改变点赞状态成功", res)
      }).catch(err => {
        console.log("改变点赞状态失败", err)
      })
    }
  },

  //跳转到评分页面
  goScorePage(e) {
    console.log(getCurrentPages())
    //判断是否授权
    let userInfo = wx.getStorageSync('userInfo')
    let that = this
    if (!userInfo) {
      that.authPublic()
    } else {
      this.setData({
        isIncloudStudentInpingfen:0
      })
      let ID = this.data.ID
      //根据ID获取课程评分详情
      wx.cloud.callFunction({
        name: "commentPlus",
        data: {
          action: "getCourseDetailById",
          id: ID,
        }
      }).then(res => {
        console.log("根据ID获取课程评分成功", res)
        let pingfen = res.result.data.pingfen
        this.setData({
          pingfen: pingfen
        })
        for (var i = 0; i < pingfen.length; i++) {
          if (pingfen[i].studentName == userInfo.nickName) {
            this.setData({
              isIncloudStudentInpingfen:1
            })
          }
        }

        if (this.data.isIncloudStudentInpingfen==1) {
          wx.showToast({
            title: '您已评分',
            icon: 'error'
          })
        } else {
          wx.navigateTo({
            url: '../score/score?id=' + e.currentTarget.dataset.id,
          })
        }
      }).catch(err => {
        console.log("根据ID获取课程评分失败", err)
      })
    }
  }
})

(3)云函数commentPlus实现代码如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
// 云函数入口函数
exports.main = async (event, context) => {
  if (event.action == 'getAllCourse') {
    return await cloud.database().collection("courseList").get()
      .then(res => {
        console.log("获取所有课程成功", res)
        return res
      }).catch(err => {
        console.log("获取所有课程失败", err)
        return err
      })
  } else if (event.action == 'getCourseDetailById') {
    return await cloud.database().collection("courseList").doc(event.id).get()
      .then(res => {
        console.log("根据ID获取课程详情成功", res)
        return res
      }).catch(err => {
        console.log("根据ID获取课程详情失败", err)
      })

  } else if (event.action == 'shoucang') {
    return await cloud.database().collection("courseList").doc(event.id).update({
      data: {
        shoucang: event.shoucang
      }
    }).then(res => {
      console.log("改变收藏状态成功", res)
    }).catch(err => {
      console.log("改变收藏状态失败", err)
    })
  } else if (event.action == 'dianzan') {
    return await cloud.database().collection("courseList").doc(event.id).update({
      data: {
        dianzan: event.dianzan
      }
    }).then(res => {
      console.log("改变点赞状态成功", res)
    }).catch(err => {
      console.log("改变点赞状态失败", err)
    })
  } else if (event.action == 'pinglun') {
    console.log(event)
    return await cloud.database().collection("courseList").doc(event.id).update({
      data: {
        pinglun: event.pinglun
      }
    }).then(res => {
      console.log("评论成功", res)
    }).catch(err => {
      console.log("评论失败", err)
    })
  } else if (event.action == 'getTitleList') {
    return await cloud.database().collection("giveScore").get()
      .then(res => {
        console.log("获取标题列表成功", res)
        return res
      }).catch(err => {
        console.log("获取标题列表失败", err)
        return err
      })
  } else if (event.action == 'addpingdfenToDb') {
    console.log(event)
    return await cloud.database().collection("courseList").doc(event.id).update({
      data: {
        pingfen: cloud.database().command.push(event.pingfen)
      }
    }).then(res => {
      console.log("添加评分成功", res)
    }).catch(err => {
      console.log("添加评分失败", err)
    })
   }
  //else if(event.action == 'getAllScore'){
  //   return await cloud.database().collection("giveScore").get()
  //     .then(res => {
  //       console.log("获取标题列表成功", res)
  //       return res
  //     }).catch(err => {
  //       console.log("获取标题列表失败", err)
  //       return err
  //     })
  // }
}

(4)数据库表的设计:

在这里插入图片描述

如上图所示,云数据库表名为sourseList,有五条课程数据,在此重点介绍字段comIsIncloudMan和dianzanMan,实现点赞功能需要就是使用这两个字段

dianzanMan:

    此字段类型为数组类型,当学生点赞评论时,就会push方法将该学生名称存入到数组中,当学生再次点赞已点评论时,就会执行splice方法将该学生名称从数组中移除,而当页面显示点赞条数就是根据该数组的长度。

comIsIncloudMan:

    此字段也很重要,应为评论学生很多,该字段时判断某一条评论是否包括当前用户,如果包括则点赞状态显示为点赞状态,即红色状态,不包括则点赞状态为未点赞状态,即为灰色。

提醒一下:本文现已实现点赞评论功能,实现类似课程的收藏和点赞是一样的原理。

总结:

    在实现的过程中,最重要的实现多个用户可以互相点赞评论,最初实现尝试多次无法实现,到最后用两个重要字段完成实现,数据库表的设计比较简单,到下文实现对课程进行评分,评分等级分为差,一般,较好,好四个等级。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值