小程序云开发一次性订阅(记录次数)功能实现

小程序云开发一次性订阅(记录次数)功能实现

项目源码链接:https://pan.baidu.com/s/1SxwMPoA6xgUwqn3O_Wpvrg
提取码:6630

产品展示
在这里插入图片描述

1.问题需求分析

需求一:由于小程序一次性订阅没有记录次数功能,所以需要开发者自己记录订阅成功的次数。
需求二:同一个模板订阅消息指定对象类型发布

2.前期准备

搜索微信公众平台进入小程序后台开启订阅服务申请选择模板获取templateId(小程序后台没有的注册一个)
在这里插入图片描述
打开微信云开发(将数据库权限设置任何人可读可写)
在这里插入图片描述

3.设计数据库

这里需要个集合一个是number(记录每个用户类型的订阅成功的次数)和subscribe(发布订阅的内容分集合)字段如图
在这里插入图片描述
在这里插入图片描述

4.设计云函数

获取openId的云函数getOpenId

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

发布订阅的云函数sendSubscribeMessage,这里的data数据格式要遵循以下格式

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
  try {
    const result = await cloud.openapi.subscribeMessage.send({
        "touser": event.openid,
        "page": 'pages/see/see?message='+event.message,
        "lang": 'zh_CN',
        "data": {
          "thing4": {
            "value": event.source
          },
          "name3": {
            "value": event.name
          },
          "thing1": {
            "value": event.content
          },
        },
        "templateId": 'UhlXQ253j8Wc3miwFz2ns_wI50RlSWS3VTiG612ocj0',
        "miniprogramState": 'developer'
      })
    return result.errCode
  } catch (err) {
    return err
  }
}

在这里插入图片描述

5.小程序代码逻辑设计

index(订阅页面)的js文件(主要是SubscribeMessage方法)
在这里插入图片描述

// index.js
// 获取应用实例
const app = getApp()
const DB_number = wx.cloud.database().collection("number")
Page({
  data: {
    list: [{
        name: '南昌大学',
        school: 0,
        tmplId: 'UhlXQ253j8Wc3miwFz2ns_wI50RlSWS3VTiG612ocj0'
      },
      {
        name: '江西师范大学',
        school: 1,
        tmplId: 'UhlXQ253j8Wc3miwFz2ns_wI50RlSWS3VTiG612ocj0'
      },
      {
        name: '南昌航空大学',
        school: 2,
        tmplId: 'UhlXQ253j8Wc3miwFz2ns_wI50RlSWS3VTiG612ocj0'
      },
      {
        name: '江西财经大学',
        school: 3,
        tmplId: 'UhlXQ253j8Wc3miwFz2ns_wI50RlSWS3VTiG612ocj0'
      },
    ],
    openid: ''
  },
  async onLoad() {
    let that = this
    let res = await wx.cloud.callFunction({
      name: 'getOpenId'
    })
    that.setData({
      openid: res.result.openid
    })
    DB_number.where({
      openid: res.result.openid
    }).get({
      success(reply) {
        // console.log(reply)
        let list0 = that.data.list.map((item, index) => {
          item.num = 0
          reply.data.forEach((item2, index2) => {
            if (item2.school === item.school) {
              item.num = item2.num
            }
          })
          return item
        })
        that.setData({
          list: list0
        })
      }
    })
  },
  getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    wx.getUserProfile({
      desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        console.log(res)
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    })
  },
  getUserInfo(e) {
    // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
    console.log(e)
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  },
  getOpenId() {
    wx.cloud.callFunction({
      name: 'getOpenId'
    }).then(res => {
      console.log(res.result.openid)
    }).catch(err => {
      console.log(err)
    })
  },
  async SubscribeMessage(e) {
    let that = this
    let school = parseInt(e.target.dataset.school)
    // console.log(res.result.openid)
    let openid = that.data.openid
    wx.requestSubscribeMessage({
      tmplIds: [e.target.dataset.tmplid],
      success(res0) {
        console.log(res0)
        if (res0[e.target.dataset.tmplid] === "accept") {
          let listNew = that.data.list.map((item, index) => {
            if (item.school === school) {
              item.num++
            }
            return item
          })
          that.setData({
            list: listNew
          })
          DB_number.where({
            openid: openid,
            school: school,
          }).get({
            success(reply) {
              //判断数据库是否有这个用户的id
              // console.log(reply)
              if (reply.data.length > 0) {
                // 修改数据
                // console.log(reply.data[0]._id, "和", reply.data[0].num)
                let num = reply.data[0].num + 1
                DB_number.doc(reply.data[0]._id).update({
                  data: {
                    num: num
                  },
                  success(res) {
                    console.log(res, "修改成功")
                  },
                  fail(err) {
                    console.log(err, "修改失败")
                  }
                })
              } else {
                // 增加一条新的数据
                DB_number.add({
                  data: {
                    openid: openid,
                    school: school,
                    num: 1
                  }
                })
              }
            }
          })
        }else{
          let listNew = that.data.list.map((item, index) => {
              item.num=0
            return item
          })
          that.setData({
            list: listNew
          })
          DB_number.where({
            openid: openid
          }).get({
            success(reply) {
              //判断数据库是否有这个用户的id
              // console.log(reply)
              if (reply.data.length > 0) {
                // 修改数据
                // console.log(reply.data[0]._id, "和", reply.data[0].num)
                // let num = reply.data[0].num + 1
                reply.data.forEach((item,index)=>{
                  DB_number.doc(item._id).update({
                    data: {
                      num: 0
                    },
                    success(res) {
                      // console.log(res, "修改成功")
                    },
                    fail(err) {
                      // console.log(err, "修改失败")
                    }
                  })
                })
              } else {
                // 增加一条新的数据
                DB_number.add({
                  data: {
                    openid: openid,
                    school: school,
                    num: 0
                  }
                })
              }
            }
          })
        }
      },
      fail(err) {
        console.log(err)
      }
    })
  },
  tologin() {
    wx.navigateTo({
      url: '/pages/login/login'
    })
  },
  /**
   * 生命周期函数--监听页面显示
   */
  async onShow() {
    let that = this
    let res = await wx.cloud.callFunction({
      name: 'getOpenId'
    })
    that.setData({
      openid: res.result.openid
    })
    DB_number.where({
      openid: res.result.openid
    }).get({
      success(reply) {
        // console.log(reply)
        let list0 = that.data.list.map((item, index) => {
          item.num = 0
          reply.data.forEach((item2, index2) => {
            if (item2.school === item.school) {
              item.num = item2.num
            }
          })
          return item
        })
        that.setData({
          list: list0
        })
      }
    })
  },
})

index的wxml代码

<!--index.wxml-->
<view style="padding:  0 30rpx;">
  <view style="display: flex;justify-content: space-between;align-items: center;margin: 50rpx 0;">
    <view>
      <view style="font-weight: 600;">开通订阅消息功能</view>
      <view style="font-size: 26rpx;color: #7a7a7a;padding: 5rpx 0;">向你发送小程序订阅消息</view>
    </view>
    <switch checked/>
  </view>
  <view style="display: flex;justify-content: space-between;align-items: center;margin: 50rpx 0;">
    <view>
      <view style="font-weight: 600;">订阅消息说明</view>
      <view style="font-size: 26rpx;color: #7a7a7a;padding: 5rpx 0;">当订阅次数为0时,无法收到对应的消息</view>
      <view style="font-size: 26rpx;color: #7a7a7a;">当订阅次数小于5时,以红色提醒</view>
      <view style="font-size: 26rpx;color: #7a7a7a;">当取消订阅时,所有订阅次数都会重置为零</view>
    </view>
  </view>
  <view style="display: flex;justify-content: space-between;align-items: center;padding: 30rpx 0;border-bottom: #7a7a7a 1rpx dotted;"
    wx:for="{{list}}"
    wx:key="{{item.school}}"
  >
    <view>
      <view style="font-weight: 600;">{{item.name}}</view>
      <view style="font-size: 26rpx;color: #7a7a7a;padding: 10rpx 0;" wx:if="{{item.num>=5}}">共订阅{{item.num}}</view>
      <view style="font-size: 26rpx;color: #ff0000;padding: 10rpx 0;" wx:else>共订阅{{item.num}}</view>
    </view>
    <button style="width: 150rpx;background-color: #07c160;color: #fff;font-size: 26rpx;margin: 0;padding: 18rpx;"
      bindtap="SubscribeMessage"
      data-tmplId="{{item.tmplId}}"
      data-school="{{item.school}}"
    >订阅+1</button>
  </view>
  <view style="position: fixed;bottom: 0;left: 0;width: 100%;text-align: center;margin: 50rpx 0;font-size: 40rpx;">or我是管理员,选择
   <text style="color: #006eff;" bindtap="tologin">登入</text>
  </view>
  <!-- <button bindtap="getOpenId">获取用户id</button>
  <button bindtap="SubscribeMessage">订阅消息</button> -->
  <!-- <button bindtap="sendSubscribeMessage">发送订阅</button> -->
</view>

index的wxss代码

/**index.wxss**/
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #aaa;
}

.userinfo-avatar {
  overflow: hidden;
  width: 128rpx;
  height: 128rpx;
  margin: 20rpx;
  border-radius: 50%;
}

.usermotto {
  margin-top: 200px;
}

发布页面send.js
在这里插入图片描述

// pages/send/send.js
const DB_number = wx.cloud.database().collection("number")
const DB_subscribe = wx.cloud.database().collection("subscribe")
const _ = wx.cloud.database().command
let timer0 = null
let timer1 = null
let timer2 = null
let timer3 = null
Page({

  /**
   * 页面的初始数据
   */
  data: {
    source: '微博',
    name: 'kkzz',
    rank: '1级',
    content: '生而为人,我很抱歉',
    school: [{
        type: 0,
        name: '南昌大学'
      },
      {
        type: 1,
        name: '江西师范大学'
      },
      {
        type: 2,
        name: '南昌航空大学'
      },
      {
        type: 3,
        name: '江西财经大学'
      },
    ],
    type: 0,
    username: ''
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.setData({
      username: options.username
    })
  },
  bindPickerChange(e) {
    this.setData({
      type: e.detail.value
    })
  },
  inputsource(e) {
    let that = this
    if (timer0) {
      clearTimeout(timer0)
    }
    timer0 = setTimeout(() => {
      that.setData({
        source: e.detail.value
      })
    }, 200)
  },
  inputname(e) {
    let that = this
    if (timer1) {
      clearTimeout(timer1)
    }
    timer1 = setTimeout(() => {
      that.setData({
        name: e.detail.value
      })
    }, 200)
  },
  inputrank(e) {
    let that = this
    if (timer2) {
      clearTimeout(timer2)
    }
    timer2 = setTimeout(() => {
      that.setData({
        rank: e.detail.value
      })
    }, 200)
  },
  inputcontent(e) {
    let that = this
    if (timer3) {
      clearTimeout(timer3)
    }
    timer3 = setTimeout(() => {
      that.setData({
        content: e.detail.value
      })
    }, 200)
  },
  async sendSubscribeMessage() {
    let that = this
    wx.showModal({
      title: '提示',
      content: '你确定要发布吗',
      success(res) {
        if (res.confirm) {
          // console.log('用户点击确定')
          let list_openid
          DB_number.where({
            school: parseInt(that.data.type),
            num: _.gt(0)
          }).get({
            success(reply) {
              console.log(reply.data)
              DB_subscribe.add({
                data: {
                  username: that.data.username,
                  school: parseInt(that.data.type),
                  name: that.data.name,
                  rank: that.data.rank,
                  source: that.data.source,
                  content: that.data.content,
                  type: parseInt(that.data.type),
                  time: new Date()
                },
                success(res0){
                  list_openid = reply.data
                  list_openid.forEach((item, index) => {
                    wx.cloud.callFunction({
                      name: 'sendSubscribeMessage',
                      data: {
                        openid: item.openid,
                        name: that.data.name,
                        rank: that.data.rank,
                        source: that.data.source,
                        content: that.data.content,
                        message:res0._id
                      }
                    }).then(res => {
                      if(item.num!==0){
                        DB_number.doc(item._id).update({data:{
                          num:item.num-1
                        }})
                      }
                      if (index === 0) {
                        wx.showToast({
                          title: '发布成功',
                          icon: 'success'
                        })
                      }
    
                      console.log(res)
                    }).catch(err => {
                      console.log(err)
                      wx.showToast({
                        title: '发布失败',
                        icon: 'error'
                      })
                    })
                  })
                }
              })      
            }
          })
        } else if (res.cancel) {
          // console.log('用户点击取消')
        }
      }
    })
  },
  before(){
    wx.navigateTo({
      url: '/pages/detailed/detailed?username='+this.data.username,
    })
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

发布页面send.wxml

<!--pages/send/send.wxml-->
<view style="padding:  0 30rpx;">
  <view>
    <view style="padding: 30rpx 0;font-weight: 600;">用户来源:</view>
    <input style="border: rgb(194, 192, 192) 1rpx solid;height: 80rpx;padding: 0 20rpx;" placeholder="例:微博" 
    bindinput="inputsource" />
  </view>
  <view>
    <view style="padding: 30rpx 0;font-weight: 600;">用户名称:</view>
    <input style="border: rgb(194, 192, 192) 1rpx solid;height: 80rpx;padding: 0 20rpx;" placeholder="例:kkzz"
    bindinput="inputname"
    />
  </view>
  <view>
    <view style="padding: 30rpx 0;font-weight: 600;">预警级别:</view>
    <input style="border: rgb(194, 192, 192) 1rpx solid;height: 80rpx;padding: 0 20rpx;" placeholder="例:1级"
    bindinput="inputrank"
    />
  </view>
  <picker mode="selector" value="{{type}}" range="{{school}}" bindchange="bindPickerChange" range-key="name">
    <view>
      <view style="padding: 30rpx 0;font-weight: 600;">发布对象:</view>
      <view style="border: rgb(194, 192, 192) 1rpx solid;text-align: center;line-height: 80rpx;height: 80rpx;padding: 0 20rpx;">{{school[type].name}}</view>
    </view>
  </picker>
  <view>
    <view style="padding: 30rpx 0;font-weight: 600;">内容:</view>
    <textarea style="border: rgb(194, 192, 192) 1rpx solid;padding: 0 20rpx;width: 640rpx;" placeholder="例:生而为人,我很抱歉"
    bindinput="inputcontent"
    />
  </view>
  <view style="color: blue;text-align: right;margin-top: 30rpx;" bindtap="before">以往发布>></view>
  <button style="position: fixed;left: 30rpx;bottom: 0;width: 690rpx;margin: 50rpx 0;background-color: rgb(77, 77, 228);color: #fff;    border-radius: 50rpx;"
  bindtap="sendSubscribeMessage"
  >发布订阅</button>
</view>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值