十小时写出一个活动通知的微信小程序

熟悉我的人都知道,我们每周都会举办一次分布式系统话题的讨论(对活动感兴趣的同学可以参考这个网址:https://donggeitnote.com/2021/07/24/topic-introduction/,当然这个不是我们今天讨论的重点),这个讨论的活动安排会发布到各个微信群,这样感兴趣的同学就可以来参加了。在上周五因为我个人的失误,没有更新活动通知中的时间,于是就导致这个活动的消息需要重新发布,这其实给帮忙发布活动的同学带来了很大的困扰。虽然最后也解决了问题,但是过程并不是很开心。所以我就想应该写个小程序来通知一下,这样一方面可以解决我们遇到的问题,比如哪次的时间再写错了,我们只要更新一下小程序内的内容就可以了。另外一方面也可以让一些主动想了解讨论话题的同学能够有一个统一的地方来发现话题。说做就做,一到周六我就开始来着手搞这件事情了。

需求分析

需求大概是我们第一步需要了解清楚的东西,在真正着手之前,我把最基本的需求简单列了一下,如下所示:

活动管理页面

这个页面是让活动发布者管理已经创建的活动以及发布新的活动,主要的功能包括以下几个方面:

  1. 显示已经创建的活动列表
  2. 创建新的活动
  3. 修改已经创建的活动
  4. 删除已经创建的活动

活动显示页面

这个页面主要是让活动的参与者知道有哪些活动,都会在什么时候举行,想参加的话还可以设置相关的提醒,所以主要的功能会包含下面这些

  1. 显示即将举行的活动
  2. 设置活动的提醒
  3. 取消活动的提醒
  4. 显示活动的详情

活动提醒

这是一个后台运行的程序,主要用来在活动即将开始之前通知已经设置提醒了的同学。

准备

搞懂了需求之后,在正式写代码之前我们还有一些工作需要去做:

首先我们需要去注册一个小程序,相应的网址是:https://mp.weixin.qq.com/cgi-bin/wx,点击前往注册就可以了,没有什么特别的,大家按步操作就可以了。这里吐槽一下就是一个邮箱只能注册一个小程序比较麻烦,我还得再申请一个新的邮箱来注册小程序,啥时微信能把这个简单的问题解决就方便多了。

在注册了小程序之后,我们需要下载微信开发者工具,可以在这个页面下载https://developers.weixin.qq.com/miniprogram/dev/devtools/devtools.html, 当然假如你是第一次使用,也可以把相关的内容读一下,熟悉一下这个工具如何使用。这个工具打开之后,大概是这个样子:

微信小程序总体架构

在准备好了相关的工具之后,真正动手写代码之前,我们再来简单了解一下微信小程序的总体架构,这样我们就可以大概知道自己需要实现些什么。微信小程序的总体架构如下图所示,我们可以看到其实微信已经帮我们做好了所有的架构相关的内容,比如我们通常说的负载均衡,集群容错,CDN加速,Redis cache,监控系统等等,我们所要做的其实很简单,只要实现小程序的前端页面和后端数据库以及两者之间的交互,也就是常说的API层就可以了。这背后的其它所有的和架构,部署相关的东西都不需要特别在意。

用户ID

在了解了相关的架构之后,我们心理有底,就可以真正着手开始写代码了。这里我们首先来思考一下上文提到的活动管理页面如何实现,我们预想中的这个页面是如下图所示的,它包含了几个部分,首先能够列出已经创建的活动列表,其次能够修改这个活动(点击笔这个图标),当然还必须要能够创建新的活动。

我们来想一下这个页面的实现,肯定是需要一个API来得到所有的活动,我们假设这个API名字是GetActivities(),只要我们通过这个API把数据库中所有符合要求的活动返回到前端之后,就只是一个列表显示的问题了。

这里比较难的一个问题就在于符合要求的活动列表,我们最初的设计是希望活动创建者只能看到/修改创建的活动。 这就需要一个用户ID来标识这个活动的创建者,当我翻开微信小程序的开发文档时,会发现其实这里有两个ID可以使用,一个是openId,一个是UnionId。

  • 简单来说openId是对于小程序来说的,也就是说同一个用户在打开微信小程序的时候都会是这一个id,它不需要用户操作和授权。
  • 而UnionId则是同一个用户在你所开发的所有的APP包括微信小程序,微信公众号,app等之间统一的ID标识,这样你就可以在小程序,公众号等之间交互数据了。当然小程序,公众号必须是同一个主体才行。

那么回归到我们的小程序,我们其实并不需要在多个应用之间进行数据交互。所以理所当然选择openId就可以了。我们可以使用一个简单的云函数来实现OpenId的获取,相关的代码如下:

我们获取了需要的openId之后,还有一个问题需要考虑,那就是什么时候来获取OpenId,可以预见的是我们大概在整个程序的运行过程中都需要使用这个id,那么把它保存到一个全局的地方显然是一个很好的方法。我们可以在app.js的onLaunch来获取,并它保存到一个全局变量中。

获取活动列表

在有了OpenId之后,我们就可以来获取已经创建的活动列表了。也就是我们上文提到的GetActivities() API。这里有两种实现:

  1. GetActivities(OpenId),这种实现中把OpenId作为参数传给后端,然后返回的结果只包含OpenId创建的活动,也就是我们想要的结果,直接以列表的方法显示出来即可。
  2. GetActivities(),获取所有人创建的活动,然后在前端在根据openId来filter出来管理者自己创建的活动,然后再显示。

这两种方法各有其优缺点,前者的好处就是它只需要返回管理者创建的活动即可,没有额外的返回。但是问题就是在这个request发送之前,它就需要openId,而我们上文的OpenId其实是一个异步调用,它什么时候能够返回并不确定。也就是说从performance的角度来说,这个GetActivites(OpenId)只能在上面的getOpenId返回之后才能执行。

而第二种方法则可以解决第一种方法的问题,它不需要等待OpenId的返回,只要在得到response做filter之前得到OpenId即可。当然它本身的问题也很明显,就是它需要返回所有人创建的活动,这个response有可能会有很多没有必要内容。

那么我们这里会选择哪一种方案呢?我们最终选择的是第二种方案,原因是从我们的角度来看,其实创建的活动量不会很多,一周也就不会超过十个,而且很多时候都是一个人创建的,所以即使选择第一种方案,可能也不能得到第一种方案的好处。所以这个最终方案的选择还是需要看你自己的使用场景是怎么样的来最终决定。

拿到activities之后再做filter,(前提也还是要判断一下openId是否是已经存在了)

创建活动

创建活动的页面大概如下所示,主要就是包含活动主题,时间,星期,以及描述。

从UI的角度来说,这个没有什么特别需要注意的,就是这里可能会有一些bind的操作,比如说我们修改了时间,那么星期也需要跟着修改,我想这个对于写过前端代码的同学来说应该会比较简单。它主要通过这样类似bindchange的操作来实现:

在创建活动之后,我们可以看到会在后端数据库中插入一条类似下面这样的数据:

应该每一个property都比较清楚,你也许会问这里的applyMembers是什么呢?我们来接着看:

提醒的设置

在活动创建并能够显示之后,一个很重要的功能就是能够及时提醒相关的用户活动即将开始。这里的页面大概如下所示:

上面是活动的显示,这个很好做,一个GetActivities()的API得到所有的活动,然后显示就可以了。这里需要考虑的是如何实现这个设置提醒的功能。这个功能包含两个方面,一个方面就是能够通过一定的机制发送提醒给用户;另一个方面就是如何知道哪些用户设置了提醒,并且在正确的时间发送提醒。

前者通知的机制肯定就是需要微信小程序来支持了,我们这里使用的“订阅消息”的功能,你可以在微信小程序后台看到这个选项:

要使用这个功能,你需要先选用一个模板或者自己创建一个模板,目前小程序的公共模板库有50个常见的订阅模板,如下所示,我们的场景也很通用,没有什么特殊的地方,所以可以直接选择其中一个。

这里假如你仔细观察,可以发现其实是支持两种订阅模式的:

  1. 一次性订阅:也就是用户授权一次,你可以发送一次通知。
  2. 长期订阅:用户授权一次,你可以发送无限次通知。

目前向个人开发者开放的是一次性订阅,长期订阅我们并不能使用,所以可以忽略。当你选择了模板之后,就会有一个模板的ID(templateId),这个id就可以用来进行订阅和发送了。

相关的订阅代码如下所示:

也就是说有用户点击了设置提醒之后,我们就需要调用这个函数来注册到相关的templateId中。同时我们需要把这个用户的id加入到我们上文提到的appplyMembers列表中,从而我们可以知道哪些用户设置了提醒了。

那么在用户设置了提醒之后,我们怎么才可以给对应的用户发送提醒呢?这里有两个问题,一个是怎么知道何时发送,这就需要我们有一个类似定时器的任务一直在后台运行,看哪个activity已经要开始了,然后决定是否要发送提醒。

要实现这个功能,我们可以使用小程序中的定时触发器功能。它主要就是会定时执行一个云函数,有了这个功能之后就方便了,如下所示,在相关的云函数中加入这个定时触发器,这里每15分钟执行一次这个函数。相关定时器的使用,大家可以参见微信的官方文档:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/triggers.html

这样每15分钟会检查一次看是否有活动要开始了,如果有,则会发送通知,发送通知可以使用下面函数来实现:

这里的templateId就是我们之前注册的templateId,需要注意的时候它的消息是有一些长度限制的,只能发送20个字符,最终的效果如下所示:

监控

至此,小程序的开发部分就基本完成了,我们最后来聊一聊监控相关的内容。就是你的小程序的使用情况,你可以通过开发工具中的云开发平台来监控:

这是整体的状况:

资源使用的情况,这个比较重要,你可以根据这个来评测你的用户量,然后评估是否需要付费运行。

当然从开发者角度来看,你而已可以看各个云函数执行的状况,比如我们上面的每15分钟运行的函数的执行情况如下:

这里你基本可以监控你所有你想知道的东西,甚至可以直接修改数据库,哈哈。

总结

至此,我们就把这个花了我10个小时肝出来的小程序写法告诉大家了,具体的小程序名字就不说了,否则被你们去尝试之后,我们的免费额度就不够用了,希望对写小程序感兴趣的同学能有所帮助。

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *