南外校园电视台微信小程序的架构演进与技术实践

南外校园电视台微信小程序的架构演进与技术实践

写在前面

今年4月份的时候,朱女士给我看了V电影的微信小程序——实现在小程序中播放视频。其优点是可以完美保留视频画质,并且无腾讯水印与贴片广告。朱女士当时跟我聊了下, 我大概构思了一下实现这个小程序的技术难点,发现都在能力范围内,便开始着手开发了。

而就在今天,电视台微信小程序 1.6.0 版本开发基本结束。这是一个重大的更新,我们添加了首页的瀑布流,关于页面……其中遇到了不少让我抓狂的困难和 Bug,但最后幸亏都解决了。所以我想写点东西,将开发中遇到的问题以及经验介绍一下。

基本架构

电视台的微信小程序结构分两部分:微信的界面、PHP的后端程序。

其中,PHP后端是重点,但因为用户直观体验的只是微信上的小程序界面,所以一直被忽视。但是,正是因为有一个如此强大的 PHP 后端程序以及服务器,小程序才能顺利平稳运行。

(微信小程序后端首页,顶部的 Jumbotron 是一段 B★RS 的视频,我岩超帅!)

(以及精心设计的 404 页面)

PHP 后端 PART.

电视台微信小程序后端是使用开源 PHP CodeIgniter 框架,并且使用 jQuery 以及 Bootstrap 前端框架。

大致的结构如下:

视频数据

其中,对于视频数据的增、删、改,是最基本的、其实现方式遵循了普通的 MVC 设计模式——通过 View 层控制界面 UI,Model 层负责数据库交互,Controller 层负责协调 View 层与 Model 层。

API

而第二个部分,API 是与微信小程序对接的。微信小程序那边 GET 请求 API,获取视频数据。API 接口的实现也是遵循了 MVC 模式,我觉得这样可能并不是很符合 RESTful Web API 的设计理念啊。

值得一提的是,分页 API 是我在开发后期所遇到的一个难点。之前一直没有做过类似的功能,所以这次也是异想天开地凭感觉写的,速度上居然还过得去!在后文中会详细讨论。

爬取CDN视频外链

请不要吐槽这个功能的名字——月色入户。这个是朱女士起的,并且他还要求要有这样的提示:

不是很懂他在想什么。看在他允许我把首页改的那么中二的份上,我便也答应了。

其中更多的技术细节也是在后文中叙述。

微信小程序 PART.

这是我第一次开发微信小程序,在看了十分钟文档后,没想到还算顺利。最初的功能只是一个视频播放页,用来从微信公众号推文进入之后开始播放视频。而当用户直接从微信首页下拉进入小程序时也只会是播放默认的一个视频。特别不友好啊~

但这次的 V1.6.0 大更新,使得小程序终于初具规模了。

其中,视频详细页与首页瀑布流是重点,这也是我花了颇多心思去修改的地方。可以说写的代码调试起来很简单,大部分时间其实是浪费在调节样式表与 UI 界面上。尤其是那个关于页面,别看它简单得很,那几行文字与 Logo 的对齐我折腾了好久。

因为对于前端的 CSS 是几乎零基础,所以各种元素的对齐排版都是靠蒙的!我只能将它的几个 CSS 属性来回换,看哪个能达到目的。比如 position 属性从 absolute 改成 reletive 再改成 fixed,直到能实现我要的效果为止。同时还要兼顾不同设备间的适配,iPhone 5 和 iPhone X 的效果瞬间不同!并且电脑上的模拟器对于 UI 的定位不是很准,我还得在手机上微信跑开发版本调试。好不容易以为搞定了,朱女士又不知道从哪搞来的 iPhone 6 Plus,说在 Plus 真机上又有问题!做下来真的是很心塞。

相关技术实践分析

PHP 后端数据操作验权

小程序的后端其实是很开放的,所有人都可以访问并且看到上面的数据,同时也都可以使用“月色入户”功能。但关于数据的操作不得不进行验权以保证安全性。所以,我的解决方式是在表单后加上一个内部 Key 的文本框,只有输入正确的 Key,操作才能被执行。

内部 Key 的文本框也作为一个字段被传到 Model 层,然后在 Model 层进行比对判断即可。

PHP 后端CDN外链爬取

这个功能最初是由朱女士提出,用来帮助今后电视台的学弟学妹们来轻松抓取视频的 CDN 外链,而不用每次按 F12 打开开发者面板翻网页代码。

实现的原理很简单,PHP 的 file_get_contents 方法直接抓取网站 HTML 内容,然后再分割查找指定的字符串即可。这和一般的爬虫原理相似。但其实并没有这么简单,PHP的字符串分割好像找不到字符串或有多个匹配字符串时总会出一些莫名其妙的 BUG,搞得人很烦。并且原网站也很复杂,在调试过程中,截取的字符串被当做 HTML 了,然后也不太能轻易发现。我曾一度想要放弃这破玩意儿,写这东西真的掉了我半条命。

最后爬取下来的最新外链数据,会被转成 json 格式,然后保存到网站根目录的 iloveBRS.txt 文件里。(不要太在意文件名,这只是爱。)当做一个缓存,之后可以直接读取这个文件,就不需要再消耗服务器资源去爬取分割字符串了。可以从 /ILoveBlackRockShooter 页面直接读取缓存。(不要太在意这个路径,这也是爱。

因为爬取数据的过程比较慢,所以在 ajax 请求中会出来一个提示正在加载的 div,就是那个“念无与为乐者”。这也都是用 jQuery 实现的。

PHP 后端分页 API 实现原理

之前听到要做瀑布流的时候,我首先的反应是数据的分页应该会比较麻烦。起初是打算使用 CodeIgniter 里自带的分页类来实现,结果发现它的分页类其实更多的是实现一个分页的导航,并且其中的 URL 重写搞得我很晕。我便打算自己构思一个分页的方法。

我的想法是这样的,外部传入当前所在页的参数,之后首先先获取数据库中的总记录数,然后计算以下值:

当前页的第一个数据的ID = (当前所在页数 -1 )*  每页的记录数

当前页的最后一个数据的ID = 当前页的第一个数据的ID + 每页的记录数

之后进入循环,将数据分条添加进入最终要返回的数组中。首先是要判断当前页的第一个数据的ID是否大于总记录数,如果大于,说明数据已经排完了,这一页是不存在的。如果不大于,则将循环中当前页的数据的ID作为索引,查找这行的数据,并逐个加入到返回的数组中。需要特殊处理的是最后一页,可能会有不足排不满的情况,这个时候还要用循环的索引总记录数比一下大小。

说得可能有些复杂,看一下代码可能会好理解一些:

最后发现这个方法确实挺好的,速度挺快的。

微信小程序视频页设计

关于视频页其实我是有点小失误的——最初开发时没有想到以后的更新,便直接把初始的 index 页面当做视频页,并且公众号推文上已经大量使用小程序了,导致后来不得不把真正的首页改名为 MainPage 来避免冲突。

但我当时有一点我也考虑的十分周到。从微信首页下拉进入小程序是不带任何参数的,但是视频页的调用是要外部传入参数,不然会报错。所以当时幸亏留了个心眼,给视频 ID 参数设置了一个默认值,让它在获取不到外部参数时默认播放今年的十大宣传片!十分机智!

微信小程序首页视频瀑布流实现

真的是很不想提这东西。这瀑布流花了我整整一天的时间去实现。然而直到现在我也没能完全摸清它的原理,有一些设置我也是不敢动,完全不知道它怎么的就能用了!我就讲讲我目前了解的吧。

首先,因为是瀑布流,就是相同的视频区块,循环不断地向下显示。所以,需要用到小程序中的模板(template)。建议是不要在当前页面的 wxml 文件中创建模板样式,而是分别建立新的 wxml 与 wxss 文件专供模板使用。

之后在页面的 wxml 与 wxss 中分别 import 模板的文件。

关于模板的循环显示,这里就是我没弄清的地方。微信中的控件循环好像是需要 wx:for 、wx:key 两个属性,同时用 data 属性指定数据来源。

之后则是拉取数据了:

值得注意的是,关于 API 的调用代码,是写在项目 utils/utils.js 中的,然后引入进行调用。

剩下的功能就是滑动到页面底部开始加载下一页的数据,这里的难点是如果页面中 scroll-view 位置不对,则无法触发 bindscrolltolower 属性的方法。腾讯官方给的小程序开发文档中说明了要限制 scroll-view 的高度才能触发,但是如果我想让 scroll-view  全屏,将 style 中的 height 设置成 100% 却没用,最后是在外面再框了个 view 才解决的。总之,就是不停地修改 css 样式才成功的。真的是很不容易了!

还有一点比较坑的是视频时间左边的那个灰色三角形,如果直接打这个特殊符号的话,在 iOS 上是会被转成超级丑的 emoji,所以最后是用了一张灰色三角形的图片来进行替代。

scroll-view 的底部分别是“加载中”与“加载完毕”的提示,分别是两个 view,然后再控制它们的 hidden 属性从而实现显示或隐藏。为了不那么单调,我将“加载完毕”改成了“获得成就”

是的,只需三秒,你就可以获得这个成就。

假的搜索框

好不容易做完了瀑布流,结果朱女士让我再加个搜索框!无良甲方!狡猾~狡猾~

搜索框的话,需要后端那边提供 API,并且搜索功能又不同于增、删、改等操作那么简单。虽然 CodeIgnite 强大的数据库类可以解决,但是在小程序这边又要排版更新 UI 搞半天。我是真的不想做。

所以嘛……朱女士说干脆搞个假的搜索框来弥补上方的空白。附上他的原话:

所以,这个假的搜索框就这么诞生了,朱女士看到了貌似还很高兴。

就是个小程序弹窗,简单的 showModal。想必以后应该会变成真的吧。

服务器相关

小程序的后端是部署在我位于洛杉矶的 VPS 上,和我的其它 Web 应用一起。因为这个应用挺重要的,所以我还为此在 UpTime Robot 上开了监控。目前也就半个月前搬瓦工那边更换服务器电力系统时出现了大约 1 个多小时的宕机,其它都还好。朱女士那边的数据显示昨天小程序有约 600 的访问量,但服务器的监控显示服务器负载一直处于较低水平。之前我们还考虑过要不要在各自的 VPS 之间搞个负载均衡的,现在想想完全没必要。

最后再说点

可以说,开发这个小程序我真的费了不少心思。它的最终效果确实也超棒!和朱女士一起合作真是太棒了!小程序的源码我并不打算开源,不过如果标价出售的话好像可以考虑一下哦~ 要知道这一套东西,淘宝上你没个一千块,根本没人愿意帮你订制开发。

同时,这个微信小程序也受到了南外集团滨海学校胡丹校长的赞赏!我本人也很荣幸能被钦点表扬。