微信小程序前后端开发快速入门(完结篇)

news2024/11/16 9:31:42

这篇是微信小程序前后端快速入门完结篇了,今天利用之前学习过的所有知识做一个新的项目「群登记助手v1.0」小程序。

整体技术架构:小程序原生前端+小程序云开发。

image.png
经历了前面教程的学习,大家有了一定的基础,所以本次分享重心主要是带着大家理清楚逻辑相关的云开发处理方案和之前未讲解过的重要组件,之前已经讲解过的重复知识就不会重新再讲解,需要大家利用之前已经学习过的知识来组合今天学习的新知识对接龙小程序进行整体的完善。

业务分析

流程分析

接龙小程序使用者角色上会有两种,分别是发起者和参与者。这个接龙是由发起者来让参与者接龙,所以他们两之间的使用逻辑是:

image.png
一共有以下七步,来完成整个接龙行为的闭环。

  1. 发起者 - 创建接龙活动
  2. 发起者 - 进入接龙列表
  3. 发起者 - 转发到微信群
  4. 参与者 - 点击程序卡片
  5. 参与者 - 进入活动详情
  6. 参与者 - 接龙信息填写
  7. 参与者 - 进入活动详情

界面如下:

image.png

数据库设计

首先数据库设计来看,我们需要三张表:

  1. 用户表(users),用于用户体系的基础搭建

image.png
2. 接龙活动表(solitaire),用于存放发起者接龙活动

image.png
3. 接龙信息表(solitaire_info),用于存放参与者接龙信息

image.png

实现路线图

难点部分会进行分析讲解,简单部分需自行实现(之前教过的知识点)

  1. 创建活动 -> 获取用户信息 -> 用户表插入用户数据 -> 活动表插入活动信息
  2. 转发活动 -> 通过联合查询出活动列表 -> 将接龙活动转发到群里
  3. 查询信息 -> 通过分享的活动ID查询详情 -> 跳转到填写信息
  4. 填写信息 -> 获取用户信息(同上)-> 信息表插入接龙信息 -> 更新活动参与人数 -> 发送订阅消息
  5. 回到详情 -> 刷新接龙信息列表(使用聚合查询)
  6. 其他功能 -> 导出表格

复杂查询

由于接龙信息和用户信息分别在两张表中实现,所以这里需要用到联表查询。这个时候就需用到小程序的聚合查询能力。

联表查询

如我们现在已经有一条活动数据了,那么现在数据库的数据结构应该是这样的:
用户表 users:

image.png
接龙表 solitaire:

image.png
然后使用 lookup 函数进行关联起来。
以下为属性含义

lookup({
  from: <要连接的集合名>,
  localField: <输入记录的要进行相等匹配的字段>,
  foreignField: <被连接集合的要进行相等匹配的字段>,
  as: <输出的数组字段名>
})

结合以上使用方式,我们使用下lookup连接查询

async queryLookupList(context, params) {
    let res = await db.collection('solitaire').aggregate()
      .match({
        openid: context.OPENID
      })
      .lookup({
        from: 'users',
        localField: 'openid',
        foreignField: '_openid',
        as: 'users',
      })
      .sort({
        date: -1
      })
      .end()
    return res
  }

最后查询出来的结果是:

[
   {
    "_id": "cd045e756110ed09047443683dd70ecf",
    "content": "312312",
    "date": "2021-08-09 16:53",
    "title": "12312",
    "type": 1,
    "openid": "oyfiv5Z90bqbQ6BJ6A273eP68j-w",
    "number": 0,
    "users": [
      {
        "_id": "8937eaa96110ea39039e900278a1529e",
        "_openid": "oyfiv5Z90bqbQ6BJ6A273eP68j-w",
        "date": "2021-08-09T08:41:29.878Z",
        "userInfo": {
          "avatarUrl": "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJ9VBHPzRxk4M7bc4xxwXOaw6DpciahEjzeZ4GP0UoSmiaqBMFQznROZlVG5ukvpv8dSXNzl34oaP7g/132",
          "city": "Changsha",
          "country": "China",
          "gender": 1,
          "language": "zh_CN",
          "nickName": "111陈宇明",
          "province": "Hunan"
        }
      }
    ]
   }
  ]

由于在实际复杂业务中,聚合查询使用的比较多的,所以再次我们带大家来对聚合查询进行更深入的了解。

聚合查询

聚合是非常强大的数据分析工具,主要用于对记录进行批量处理,可以对记录进行按条件分组、跨集合联表等一系列批量而又复杂操作。类似于Excel整列整列跨字段的运算(如加、减、合并、比较等)、对内嵌的字段可以进行整列拆分、类型变换、组合等。

聚合查询 VS 普通查询

聚合aggregate和普通数据查询get是两套不同的体系,聚合更偏向于数据的复杂查询。聚合查询和普通数据查询都能对数据库进行查询,两个的很多方法都特别类似,我们可以通过对之前普通查询的理解来理解聚合查询的部分功能,具体查看以下表格对比。

image.png
在这里需要注意的是使用聚合查询之前需要先 aggregate() 发起一个聚合操作。以上是普通查询可以做到的,聚合查询也可以做到,接下来是普通查询做不到的。

聚合阶段

聚合阶段是聚合管理流水线作业的组成单元,是一个个功能节点,有的可以联表lookup、有的可以组合group、有的可以拆分unwind等等。每个聚合阶段可以使用表达式、操作符对输入文档进行计算综合、均值、拼接、分割、转换格式等操作,操作完成之后会输出给下一个阶段,直到end返回结果。

image.png

小技巧

在这里告诉大家一个小技巧,其实写查询的时候可以在数据库的高级操作区间先写好测试然后再放到函数中去使用,这样可以提高效率。

image.png
在这里不需要获取数据库对象,直接通过db就能使用,数据也不需要打印出来,只要使用了结束函数就可以了。

订阅消息

当发起者转发到群里之后,参与者就可以填写接龙信息,当接龙信息填写完成之后,可以在这里给到参与者发送一个订阅消息,告知参与者接龙成功。

这样设计有两个好处:

  1. 便于再次激活用户,多一个入口就多一些用户打开的概率。
  2. 更快捷的打开方式(提升1倍的效率)
  3. 正常打开路径:
  4. 下拉聊天界面进入小程序列表
  5. 点击接龙小程序
  6. 找到参与的接龙活动
  7. 找到具体接龙点击查看详情
  8. 订阅模版
  9. 进入服务通知列表
  10. 找到具体模版点击查看详情

那么如何给用户发送订阅消息呢?请接着往下看:

申请消息模版

第一步,先登录到后台,找到订阅消息菜单->申请订阅消息模版

image.png

第二步,进入订阅消息列表页面,点击选用按钮

image.png

第三步,进入选用模版库,通过关键词搜索进行查找,消息模版和小程序的类目有关,以“接龙”为例,小程序类目是「预约/报名,笔记」所以搜索到了这两个类目下的消息模版。

image.png

第四步,选择自己需要的模版,点击「选用」进入详情页面。模版有很多关键词,只需要勾选自己需要的关键词即可,然后填写下场景说明即可点击提交

image.png

第五步,填写完成后,会在我的模版看到刚才申请好的消息模版,复制模版ID即可,到时候然后切换到小程序端进行使用

image.png

获取订阅授权

第六步,找到小程序需要让用户授权的触发方法。如:需求是当用户填写完成接龙资料,让用户授权报名成功提醒,然后发一条报名成功的订阅消息,那么这个时候就需要找到填写信息的方法。如果只是单独先对这个功能进行学习,那么就可以在一个页面写个按钮,然后按钮绑定一个点击事件触发即可。

写在任意测试页面wxml

<button bindtap="onMsg" >测试订阅消息</button>

当前测试页面对应的js

wx.requestSubscribeMessage({
      tmplIds: ['模版ID'], 
      success(res) {
        console.log(res)
      }
    })

第七步,用真机调试,模拟器不支持。点击之后界面会出现授权页面。

image.png

以下为我分别点击取消和允许的日志输出。用户可以支持一次调用最多可订阅3条消息。

image.png

然后我们再来看下 requestSubscribeMessage 文档中对返回体的解释

image.png

对于开发者来说,需要关心的就是是否用户允许来,所以我们需要通过以下方式获取结果,当结果是允许的时候我们插入就发送成功通知给到用户即可。当然我这里指的是用户添加完后发送添加成功通知的业务路径,如果不是需要当前动作完成后发送的话,那么就需要存储一条记录到数据库,等需要用到的时候再去做发送消息模版的动作。

onMsg() {
    wx.requestSubscribeMessage({
      tmplIds: ['模版ID'],
      success(res) {
        if(res.模版ID=='accept'){
          // 发送消息给到用户
        }
      }
    })
  }

发送模版消息

第七步,发送模版消息,新建一个发送模版消息的云函数 sendMessage ,然后打开 subscribeMessage. send 文档,可以看到这个方法支持云调用,也就是说官方已经帮开发者封装好了方法使用起来非常简单。

云调用是云开发提供的基于云函数使用小程序开放接口的能力

image.png

那么我们就用云调用方法来试试,首先在 sendMessage 的config.json文件配置权限

{
  "permissions": {
    "openapi": [
      "subscribeMessage.send"
    ]
  }
}

然后在js中编写调用发送模版消息的方法,方法参数如下:

image.png

我把重要的参数用红色框框标记起来了,看下代码。

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

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const result = await cloud.openapi.subscribeMessage.send({
    "touser": wxContext.OPENID, // 发给自己直接从 getWXContext 获取
    "templateId":'模版ID',
    "page": '目标页面路径',
    "lang": 'zh_CN',
    "data": {
      "thing2": {
        "value": '报名接龙2021'
      },
      "phrase8": {
        "value": '报名成功'
      },
      "thing19": {
        "value": '详细点击查看=>'
      }
    },
    "miniprogramState": 'developer'
  })
  return result
  
}

注意 data 这个参数需要回到小程序管理后台的消息订阅列表查看订阅模版的详情

image.png

这里需要注意每个不同的数据类型都有些限制条件详细可见文档,然后data参数需要和上面的模版内容一对一对应上,方法写完上传并部署即可。

第八步,调用模版消息。

onMsg() {
    wx.requestSubscribeMessage({
      tmplIds: ['模版ID'],
      success(res) {
        if (res.XXXXID == 'accept') {
          wx.cloud.callFunction({
            name: 'sendMessage'
          }).then(res => {
            console.log(res)
          })
        }
      }
    })
  }

调用成功后会在微信聊天页面的服务通知中收到模版消息提醒,点击即可进入小程序,效果如下:

image.png

导出表格

使用云函数使用Node.js的node-xlsx模块

安装模块

  1. 新建云函数 excel
  2. 右键云函数选择在外部终端窗口开打

image.png

  1. 输入命令
npm install node-xlsx
  1. 安装成功

image.png

  1. 文件结构

image.png

使用模块

  1. 导入模块
const xlsx = require('node-xlsx') 
  1. 准备数据
let row = ['姓名', '电话', '备注']; //表格的属性
  let allData = [] //表格内容
  // 添加表头
  allData.push(row)
  // 假数据,真实数据需要从小程序端传递过来或在云函数中云数据库查询出来
  allData.push(['陈宇明', '13148123123', ''])
  allData.push(['陈X明', '13148123123', '不知道'])
  1. 生成表格
// 生成表格
  var buffer = await xlsx.build([{
    name: 'mySheetName',
    data: allData
  }]);
  1. 最后生成完成之后还需要用到我们之前学习过的上传文件 uploadFile 上传到云存储中
 let cloudPath = `xlsx/${Math.floor(Math.random()*1000000000)}.xlsx`
//上传文件返回结果
  return await cloud.uploadFile({
    cloudPath: cloudPath,
    fileContent: buffer, //excel二进制文件
  })
  1. 调试一下

image.png

  1. 查看文件

image.png

  1. 通过复制下载链接,打开查看表格内容

image.png

在线查看文档

当获取到文件ID,在使用 getTempFileURL 用云文件 ID 换取真实链接,然后 downloadFile 下载文件资源到本地,通过 openDocument 新开页面打开文档。

openExcel(){
    wx.cloud.callFunction({
      name: "excel",
      data: {
        infos: {} //表格数据
      },
      complete: res => {
        wx.cloud.getTempFileURL({
          fileList: [res.result.fileID],
          success: res => {
            this.setData({
              tempFileURL: res.fileList[0].tempFileURL
            })
            console.log(this.data.tempFileURL)
            wx.downloadFile({
              url: this.data.tempFileURL,
              success: (res) => {
                const filePath = res.tempFilePath
                console.log(filePath)
                wx.openDocument({
                  filePath: filePath,
                  showMenu: true,
                  success: res => {
                    console.log(res)
                  }
                })
              }
            })
          }
        })
      }
    })
  },

复制下载链接

当获取到文件ID,在使用 getTempFileURL 用云文件 ID 换取真实链接,然后 setClipboardData 设置系统剪贴板的内容。

 getExcelUrl() {
    wx.cloud.callFunction({
      name: "excel",
      data: {
        infos: {} //表格数据
      },
      complete: res => {
        wx.cloud.getTempFileURL({
          fileList: [res.result.fileID],
          success: res => {
            this.setData({
              tempFileURL: res.fileList[0].tempFileURL
            })
            wx.setClipboardData({ //复制到粘贴板
              data: this.data.tempFileURL,
              success(res) {
                wx.getClipboardData({
                  success(res) {
                  }
                })
              }
            })
          }
        })
      }
    })
  },

最后

这篇教程相比之前的备忘录教程更像是一道填空题,需要大家利用之前教程学习到的知识进行融合才能实现这个小程序,独立完成这个项目才是检验学习效果的最佳方式。

学习更多小程序云开发知识请关注CRMEB开源项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/887529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SOFABoot——基本使用(笔记)

文章目录 一、前言二、快速开始2.1 基本搭建2.2 测试是否成功2.3 其他部分日志测试异步启动 三、SOFABoot的模块化开发3.1 基于Spring上下文的隔离3.2 Root Application Context3.3 模块并行化启动3.4 JVM服务与RPC服务的发布与引用3.5 模块配置Module-NameRequire-ModuleSprin…

深入理解JVM——垃圾回收与内存分配机制详细讲解

所谓垃圾回收&#xff0c;也就是要回收已经“死了”的对象。 那我们如何判断哪些对象“存活”&#xff0c;哪些已经“死去”呢&#xff1f; 一、判断对象已死 1、引用计数算法 给对象中添加一个引用计数器&#xff0c;每当有一个地方引用它时&#xff0c;计数器就加一&…

在IDEA中创建properties配置文件

第一步&#xff1a;在 src路径下找到resources文件 第二步&#xff1a;右击选择新建Resource Bundle配置文件 第三步&#xff1a;为Resource Bundle配置文件命名 完成创建

高效反编译luac文件

对于游戏开发人员,有时候希望从一些游戏apk中反编译出源代码,进行学习,但是如果你触碰到法律边缘,那么你要非常小心。 这篇文章,我针对一些用lua写客户端或者服务器的编译过的luac文件进行反编译,获取其源代码的过程。 这里我不赘述如何反编译解压apk包的过程了,只说重点…

k8s的pv和pvc创建

//NFS使用PV和PVC 1、配置nfs存储 2、定义PV 实现 下图的pv和pvc测试 pv的定义 这里定义5个PV&#xff0c;并且定义挂载的路径以及访问模式&#xff0c;还有PV划分的大小 vim /pv.yamlapiVersion: v1 kind: PersistentVolume metadata:name: pv001 spec:capacity:storage: …

【目标检测】目标检测 相关学习笔记

目标检测算法 PASCALVOC2012数据集 挑战赛主要分为 图像分类 目标检测 目标分割 动作识别 数据集分为四个大类 交通&#xff08;飞机 船 公交车 摩托车&#xff09; 住房&#xff08;杯子 椅子 餐桌 沙发&#xff09; 动物&#xff08;鸟 猫 奶牛 狗 马 羊&#xff09; 其他&a…

Java 单例模式简单介绍

何为单例模式 所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法。 实现思路 如果我们要让类在一个虚拟机中只能产生一个对象&#xff0c;我们首先必…

MBR400100CT-ASEMI肖特基模块MBR400100CT

编辑&#xff1a;ll MBR400100CT-ASEMI肖特基模块MBR400100CT 型号&#xff1a;MBR400100CT 品牌&#xff1a;ASEMI 封装&#xff1a;M2 正向电流&#xff1a;400A 反向电压&#xff1a;100V 引线数量&#xff1a;2 芯片个数&#xff1a;2 芯片尺寸&#xff1a;102MIL…

计算机竞赛 python+深度学习+opencv实现植物识别算法系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的植物识别算法研究与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;4分 &#x1f9ff; 更多…

FPGA: RS译码仿真过程

FPGA: RS译码仿真过程 在上一篇中记录了在FPGA中利用RS编码IP核完成信道编码的仿真过程&#xff0c;这篇记录利用译码IP核进行RS解码的仿真过程&#xff0c;带有程序和结果。 1. 开始准备 在进行解码的过程时&#xff0c;同时利用上一篇中的MATLAB仿真程序和编码过程&#x…

【LeetCode每日一题】——1331.数组序号转换

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 简单 三【题目编号】 1331.数组序号转换 四【题目描述】 给你一个整数…

将SM2根证书预置到chromium中

最近花了很多精力在做chromium的GmSSL适配&#xff0c;协议和算法都已经完成&#xff0c;这篇文章是关于将SM2根证书预置到chromium中 我的开发测试环境是macos12.4&#xff0c;从chromium的代码和文档中得知证书获取和校验都是通过操作系统以及native api接口完成&#xff0c…

leetcode 917.仅仅反转字母

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;仅仅反转字母 ps&#xff1a; 这道题思路很简单&#xff0c;只需要一个下标在前一个下标在后&#xff0c;分别找是字母的字符&#xff0c;找到之后交换即可。 代码&#xff1a; class Solution { public:bool isAlpha …

QT:鼠标事件

鼠标事件&#xff08;QEvent&#xff09; 把帮助文档里面搜索QEvent则可查看相关内容&#xff0c;举例 鼠标进入的事件EnterEvent&#xff0c;是一个虚函数&#xff0c;对应的还要进入的函数leaveEvent 新建一个类&#xff0c;作为新的控件&#xff0c;打印鼠标事件 #inclu…

Unity UI内存泄漏优化

项目一运行&#xff0c;占用的内存越来越多&#xff0c;不会释放&#xff0c;导致GC越来越频繁&#xff0c;越来越慢&#xff0c;这些都是为什么呢&#xff0c;今天从UI方面谈起。 首先让我们来聊聊什么是内存泄漏呢&#xff1f; 一般来讲内存泄漏就是指我们的应用向内存申请…

W6100-EVB-PICO 做UDP Client 进行数据回环测试(八)

前言 上一章我们用开发板作为UDP Server进行数据回环测试&#xff0c;本章我们让我们的开发板作为UDP Client进行数据回环测试。 连接方式 使开发板和我们的电脑处于同一网段&#xff1a; 开发板通过交叉线直连主机开发板和主机都接在路由器LAN口 测试工具 网路调试工具&a…

JAVA基础知识(二)——程序流程控制

程序流程控制 一、程序流程控制1.1 程序流程控制1.2 顺序结构1.3 分支结构1.4 循环结构1.5 嵌套循环1.6 return的使用 一、程序流程控制 1.1 程序流程控制 流程控制语句是用来控制程序中各语句执行顺序的语句&#xff0c;可以把语句组合成能完成一定功能的小逻辑模块。 其流程…

Vue2-TodoList案例

TodoList案例 组件化编码流程&#xff08;通用&#xff09;整体思路1、分析结构2、拆html和css3、初始化列表4、实现添加列表功能5、实现勾选功能6、实现删除功能7、实现底部统计功能8、实现全选框的交互&#xff08;1&#xff09;每个todo控制全选框&#xff08;2&#xff09;…

第7章 C控制语句:分支和跳转

本章介绍以下内容&#xff1a; 关键字&#xff1a;if、else、switch、continue、break、case、default、goto 运算符&#xff1a;&&、||、?: 函数&#xff1a;getchar()、putchar()、ctype.h系列 如何使用if和if else语句&#xff0c;如何嵌套它们 在更复杂的测试表达…

SpringBoot的配置文件(properties与yml)

文章目录 1. 配置文件的作用2. 配置文件格式3. 配置文件的使用方法3.1. properties配置文件3.1.1. 基本语法和使用3.1.2. properties优缺点分析 3.2. yml配置文件3.2.1. 基本语法与使用3.2.2. yml中单双引号问题3.2.3. yml配置不同类型的数据类型及null3.2.4. 配置对象3.2.5. 配…