可使用图片与 Emoji 表情的实时留言板+聊天室

分析微信公众号原生交流方式的痛点,分享利用 Socket.io 开发实时留言板系统的实战心得。文章详细记录了解决移动端输入框失焦导致键盘收回、MySQL 处理 4 字节 Emoji 表情存取、多用户 WebSocket 房间隔离以及安卓版微信滚动性能优化等关键技术难题。

起因

以前微信公众号使用的留言板就是就是用户给公众号发消息 然而随着公众号功能的增加,用户的爆炸式增长,这样的留言方式越来越不方便,存在以下一些问题:

  • 用户留言时如果输入一些特定的词语(一些模块关键词),会被认为是用户想使用该功能,导致留言失败
  • 用户留言结束后,未及时退出留言状态,导致用户后续发送的消息依旧被当作留言处理
  • 当管理员回复留言时,用户直接回复可能也是无效的
  • 由于图片消息默认被某模块定义,导致用户无法发送异常截图给我们

于是就自己用 Socket.io 来写一个简单留言板,下面记录下编写时碰到的一些问题

点击发送按钮时,键盘会收回

input

如图所示,由于发送按钮是个 Button,当用户点击发送后,由于输入框失去了聚集,键盘就会自动收回。然而,这对于用户体验来说问题十分大的经过学长(小王加贝)的指导,将按钮用Input标签代替,用CSS将Input改成Buton的模样,当点击时继续聚焦到文字输入框,这样由于发送和输入都是输入框,键盘自然就不会收回了。

Emoji 表情的处理与显示

emoji

Emoji 的处理是非常蛋疼的

  • 首先,在服务器端,用的是 MySQL,MySQL 默认 utf8 编码最多只能存 3 个字节,然而 Emoji 表情是 4 个字节的,根本就存放不下,谷歌了下,大多数是说改 MySQL 编码为 utf8 mb4_general_ci,然而因为某些原因不能使用这种方式,最后选择了转码,判断 当字节数大于3的就进行转码处理

  • 其次,在客户端怎么显示呢,在微信里面 Emoji 是无法显示的,那么只能结合 Emoji 的表情的编码写正则,正则到表情后将表情编码替换为对应的表情图片

  • 那么,问题来了,刚开始不清楚情况,正则时只处理了 Softbank 这一种 Emoji 版本,然后使用时发现部分手机发送的 Emoji 表情都无法显示,仔细一研究发现,原来 Emoji 存在很多版本,常见的有 Unified、DoCoMo、KDDI、Softbank、Google,然而不同的手机使用的 Emoji 版本不一定一样。

  • 在尝试将其他版本的 Emoji 编码转化为 Softbank 编码然后再来显示时,问题又来了,Softbank 版本表情是相对较多的,DoCoMo 版本表情相对较少,存在 DoCoMo 版本一个表情对应多个 Softbank 表情的情况,然后映射到了不一致的表情,导致错误的显示结果。

最终,选择了DoCoMo表情版本来显示,其他的版本的Emoji表情统一转换到DoCoMo版本的Emoji表情

多用户的处理问题

留言板嘛,由于存在多用户与多管理员,又涉及到管理权限的问题,考虑的逻辑相对复杂一些

  • 由于聊天时通过 WebSocket 实现的。然而留言又是私密留言的,那么当有多个用户同时留言时,一个用户的留言不能推送到其他的用户的 WebSocket 下,然而当一个用户留言时可能有一个或多个管理员在留言页面,那么用户消息肯定要推送给解决这个用户问题的管理员,而不能推送给解决其他用户问题的管理员,然后如果用户或者管理开了多个留言窗口,那么用户或管理员在其他窗口发送的消息也要同步显示

  • 由于聊天室的需要,这个留言板要升级为聊天室,所以还存在一(多)个用户对一(多)个用户的情况

  • 由于消息及时性的需要,如果没有管理员在于用户交流的时候,用户的消息肯定要通知到管理员的微信上,交流时,消息不能同时微信骚扰管理员,同理,管理员的消息也要通知到用户。

滑动卡顿问题

  • 刚开始时,所有的消息都在一个 DIV 里面滚动,测试过所有主流浏览器(桌面版与移动版都测试过),滑动非常流畅,然而,不知什么情况,就在安卓版本微信里面使用时(IOS 不存在这个问题),非常的卡顿,根本就是滑不动。

  • 研究分析半天就是没有找到问题所在,应该是微信本身的问题(可以随便用 BootStrap 建个网页,然后使用模态框,将内容填充到需要滚动,然后用微信访问,滑动,就能体验这种感觉了)

  • 鉴于在 body 里面滑动是不存在卡顿的,只有去掉了 div,调整布局,然后滑动正常了

后记

我们共同开发的两个人都是后端的,然而一些简单的前端页面又是必须的,用的都是原生 CSS,界面虽一般,但能用就行

发送图片 聊天