系统分析设计期末大项目——闲得一币TimeForCoin小程序前端
小程序项目地址_闲得一币

概述

实时会话系统包括两大部分:消息管理系统和会话系统。其中“消息”可以定义为一系列会话(即双方之间会话)的集合。通过获取消息列表,我们可以看到很多个消息,每一个消息都有对应的消息id。而通过消息的id,我们可以获取一系列会话,如下:

消息管理页

消息管理页将获取的消息分为个人消息以及系统消息。系统消息不能够被回复而个人消息可以。
Message.json中我们需要添加:"enablePullDownRefresh": true以允许下拉刷新。而对于下拉刷新,我们可以通过onPullDownResfresh()函数实现。除此之外,我们还需要在onShow函数中添加信息获取的功能(还要有登录状态的判断)。

onShow函数

 onShow: async function() {this.setData({hasUserInfo: app.globalData.hasUserInfo})//登录判断if (!this.data.hasUserInfo) {wx.showToast({title: '您未登录~',image: '/images/icons/error.png'})setTimeout(function() {// 返回wx.switchTab({url: '/pages/index/index',success: function(res) {},fail: function(res) {},complete: function(res) {},})}, 1000);}await this.loadMessage(1)},

onPullDownRefresh函数

onPullDownRefresh: async function () {if(!this.data.isLoading){await this.loadMessage(null)}},

至于为什么是onShow而不是onLoad,因为onShow函数在你离开该页面重新进入(可以通过onNavigateBack返回)该页面的时候也会执行一次。消息的状态包括未读已读,如果使用onLoad函数从会话列表页面返回时未读不会更新为已读
在获取消息的函数loadMessage内,我们需要进行https请求,并根据请求的结果(状态码以及数据)进行消息的显示。如果状态码不为200,需要进行异常处理,这里是显示toast。而对于获取的消息,我们根据当前用户选择的是个人消息还是系统消息进行分类,如果选择个人消息就只显示个人消息。除此之外,还需要moment.js进行时间数据的解析。当然,除了时间,所有的数据都要进行正确显示。

当然了,这是个异步函数,因为其中需要等待https请求的结果。
消息页比较有挑战性的是自动刷新ScrollView到底端,使得有新的信息来的时候会自动显示。

loadMessage函数

loadMessage: async function(page) {this.setData({isLoading: true})if(page != null){this.data.currentPage = pagethis.data.systemMessage = []this.data.chatMessage = []} else{this.data.currentPage++}const res = await server.request('GET', 'messages',{page: this.data.currentPage,size: 10})this.setData({isLoading :false})if(res.statusCode !== 200){this.setData({hasUserInfo: false})wx.showToast({title: '网络错误',icon: '',image: '/images/icons/error.png',duration: 0,mask: true,success: function(res) {},fail: function(res) {},complete: function(res) {},})this.setData({noMore: true})return}if(!res.data.data || res.data.data.length === 0){this.setData({noMore: true})this.data.currentPage--return}moment.locale('en', {longDateFormat: {l: "YYYY-MM-DD",L: "YYYY-MM-DD HH:mm"}})for (let i in res.data.data) {res.data.data[i].string_last_time =moment(res.data.data[i].last_message.time * 1000).format('L');if (res.data.data[i].target_user.nickname.length > 10) {res.data.data[i].target_user.nickname = res.data.data[i].target_user.nickname.substr(0, 10) + '...'}if (res.data.data[i].type === 'chat') {this.data.chatMessage.push(res.data.data[i])} else {res.data.data[i].target_user.avatar = '/images/icon.png'this.data.systemMessage.push(res.data.data[i])}}if(!this.data.showSystemInfo){this.setData({testMessage: {data: this.data.chatMessage}})} else{this.setData({testMessage:{data: this.data.systemMessage}})}},

当然,我们还需要添加单击事件。在标签中添加对应的data-item为消息id,之后根据对应的消息id进行跳转(到会话列表中)。

// 跳转详情navigateToMessageDetail: function(e) {var id = e.currentTarget.dataset.id;wx.navigateTo({url: '/pages/MessageDetail/MessageDetail?session_id=' + id + '&status=message',})},

会话列表页

在会话列表页中,根据消息id进行会话列表的获取。

获取新会话

通过setTimeOut实现定时获取新消息。当然与其他数据一样,列表是分页进行获取的。但与其他数据不同,越接近底部会话的时间是更新的,而通过api获取的页面下标越小是越新的,所以通过调用reverse函数实现反转。如果获取多个页面,还需要进行反转后叠加。

if(isMore){var arr = []res.data.messages = res.data.messages.reverse()for(var val of res.data.messages){arr.push(val)}for(var val of this.data.testMessageDetail.data){arr.push(val)}if(res.data.type !== 'chat'){// 系统消息不进行整点判断for (var i = 0; i < arr.length; i = i + 1) {arr[i].string_time = moment(arr[i].time * 1000).format('L');arr[i].showTime = true;}

时间的解析

与之前的时间解析不同,如果对于每一条会话的时间都进行显示,就显得特别繁琐和难看了。这里模仿微信,在每一分钟才进行一次的会话时间的显示。这就需要判断每两个会话之间的时间差是否大于一分钟的。除此之外,第一条会话一定要显示其时间,否则用户无从判断。
实现如下:

// 用于时间显示moment.locale('zh-cn', {longDateFormat: {l: "YYYY-MM-DD",L: "YYYY-MM-DD HH:mm"}})
...// 系统消息不进行整点判断for (var i = 0; i < arr.length; i = i + 1) {arr[i].string_time = moment(arr[i].time * 1000).format('L');arr[i].showTime = true;}} else{// 整点判断for (var i = 0; i < arr.length - 1; i = i + 1) {if ((arr[i + 1].time - arr[i].time) > 60 || i === 0) {arr[i].string_time = moment(arr[i].time * 1000).format('L');arr[i].showTime = true;}}}this.setData({testMessageDetail: {data: arr},});

判断自己和对方

这里通过全局变量中的用户id进行己方和对方的判断。如果是对方则显示白底黑字,而己方则显示主题色底和白色字。己方在右边而对方在左边。通过两个不同的view标签并且通过wx:if实现这种效果。

 <view wx:if="{{!item.self}}" style="display:flex; flex-direction: row; padding: 10rpx 30rpx; margin-top: 20rpx; width: 100%"><image class="ava" src="{{item.target_user.avatar}}" /><view class="details"><text class="username" style="text-align:left;">{{item.target_user.nickname}}</text><text class="content" style=" opacity: 0.8;max-width:70%;">{{item.content}}</text></view></view><view wx:if="{{item.self}}" style="display:flex; flex-direction: row; padding: 10rpx 30rpx; margin-top: 20rpx;justify-content:flex-end;"><view class="details" style="align-items:flex-end;"><text class="username" style="text-align:right;">{{item.target_user.nickname}}</text><text class="content" style="background-color:#ff7e67; color:white;">{{item.content}}</text></view><image class="ava" src="{{item.target_user.avatar}}" /></view></view>
}// 记录会话IDthis.data.session_id = res.data.idthis.data.status = 'message'this.data.target_user_id = res.data.target_user.idfor (let i in res.data.messages) {if (res.data.messages[i].user_id === res.data.target_user.id) {res.data.messages[i].target_user = res.data.target_userres.data.messages[i].self = false} else {res.data.messages[i].target_user = {nickname: app.globalData.userInfo.info.nickname,avatar: app.globalData.userInfo.info.avatar}res.data.messages[i].self = true}}

自动获取新消息

这里通过setTimeOut实现循环获取消息,延时设为5s,避免过多的请求。在每一次获取新消息后,都需要将ScrollView调整到最底部。下面会叙述其方法。
自动获取消息的时候,与第一次获取类似,只获取第一页,历史记录的获取使用触顶触发。

autoLoadMessage: async function(){var res = await server.request('GET', 'messages/' + this.data.session_id, {page: 1,size: 1})if(res.data.length === 0) {}else{var last = this.data.testMessageDetail.data[this.data.testMessageDetail.data.length - 1]var getLast = res.data.data.messages[0]if (getLast.content === last.content && getLast.time === last.time){}else{if (getLast.user_id === res.data.data.target_user.id) {getLast.target_user = res.data.data.target_usergetLast.self = false} else {getLast.target_user = {nickname: app.globalData.userInfo.info.nickname,avatar: app.globalData.userInfo.info.avatar}getLast.self = true}moment.locale('en', {longDateFormat: {l: "YYYY-MM-DD HH:mm",L: "YYYY-MM-DD HH:mm:ss"}})getLast.string_time = moment(getLast.time * 1000).format('L')getLast.showTime = falsethis.data.testMessageDetail.data.push(getLast)this.setData({testMessageDetail:{data: this.data.testMessageDetail.data}})this.setData({top_value: 100 * this.data.testMessageDetail.data.length,})}// if (getLast.content === (this.data.testMessageDetail.data.reserve()[0]).content){// }else{//   // this.data.testMessageDetail.data.push(res.data.data.)// }}setTimeout(this.autoLoadMessage, 5000)}

ScrollView与触顶触发

触顶触发中,wxml使用如下:

 <scroll-view bindscrolltoupper="onMsgRefresh" id="dialog_list" scroll-y="{{true}}" scroll-with-animation='{{true}}' scroll-top='{{top_value}}'>

onMsgRefesh函数中,需要进行另一页面的获取,得到新的页面数据后,需要与之前的数据整合,并对整合后的数据进行时间显示的判断。

    if (!this.data.isLoading && !this.data.noMore){this.data.page = this.data.page + 1this.loadMessage(this.data.session_id, this.data.status, true)}},

除此之外,当然还需要正在加载中没有更多的显示。这里不多赘述。

ScrollView自动触底

这里需要考虑另外一个问题,新的会话已经获取,但是ScrollView并没有滚动到最底部,新的消息被遮挡了。这就需要让ScrollView滚动到最底部。对于这个标签,需要设定固定的大小,并且将scroll-top双向绑定。在获取新的数据后,进行如下设定:

 this.setData({top_value: 100 * this.data.testMessageDetail.data.length,})

去其中100需要根据实际情况而设定。

底部对话栏

这个的实现与之前详情页的评论栏/回复栏类似,不多赘述,欢迎大家看我的另一篇博客(地址在最上面)。

如何在微信小程序中实现实时会话(聊天)系统相关推荐

  1. 微信小程序中,需要注意ios系统的坑: 日期不识别横杠“-”符、输入框设置maxlength时,拼音也会被限制……

    1.小程序ios端,日期不识别横杠"-"符 在开发小程序的项目中,对接口返回的时间格式,有时为"2021-03-20 11:28:50",前端对该格式转为时间戳 ...

  2. 小程序中的实时日志,直接在微信公众号可以看到数据

    前言: 小程序中的实时日志,直接在微信公众号可以看到数据. 具体操作: 注意:小程序实时日志每天的条数就大为100w条 1.封装的log.js方法,放到utils里面 var log = wx.get ...

  3. 微信小程序中播放海康萤石云HLS '.m3u8'视频 video标签

    微信小程序中播放海康萤石云HLS '.m3u8'视频 video标签 前言 萤石云开放平台 微信开发者工具 前言 因为项目需要在微信小程序上展示实时视频流信息,以下内容是我将萤石云平台官方文档和自己实 ...

  4. GoEasy在微信小程序中的应用

    目录 介绍: 正文: 登录自己的微信公众平台 初始化GoEasy对象 接收消息 发送消息 最后: 介绍: GoEasy作为快速构建web实时通讯体系API之一,能够让websocket变得更简单! 正 ...

  5. 地图围栏 小程序_IoT:GPS 和地理围栏实现微信小程序中马拉松全程追踪实战

    本场 Chat 将围绕近年火爆的网红运动马拉松比赛场景,通过 IoT 物联网技术,你可以在微信小程序中实时追踪好友的马拉松全程轨迹:通过电子围栏技术划定终点范围,当好友跑入终点区域,立即通知你去拍照留 ...

  6. 微信小程序setinterval_微信小程序中setInterval的使用方法

    微信小程序中setinterval的使用方法 看了下小程序的画布功能,简单的使用了一下,用蹩脚的逻辑做了个 "弹啊弹,弹走鱼尾纹的小球",一起来看下吧.过程不重要主要是画布的使用哦 ...

  7. Canvas绘图在微信小程序中的应用:生成个性化海报

    Canvas绘图在微信小程序中的应用:生成个性化海报 如极客时间的一些实现案例: 基础语法 Canvas本质是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素,默认大小为30 ...

  8. 微信小程序中this指向作用域问题this.setData is not a function报错

    在微信小程序中我们一般通过以下方式来修改data中的数据 this.setData({index1: e.detail.value}) 比如在函数里面修改数据 bindFaChange1: funct ...

  9. 在微信小程序中绘制图表(part2)

    本期大纲 1.确定纵坐标的范围并绘制 2.根据真实数据绘制折线 相关阅读: 在微信小程序中绘制图表(part1) 在微信小程序中绘制图表(part3) 关注我的 github 项目 查看完整代码. 确 ...

最新文章

  1. Lnmp安装与配置笔记
  2. redis-5.0.4集群部署
  3. 10的多少次方 oracle_初中数学:关于一元二次方程的中考经典例题,千万别错过!...
  4. eclipse中anroid adk添加
  5. jsonwebtoken jwt token 简单加密
  6. 阿里云Https部署网站
  7. MATLAB中神经网络train函数使用说明
  8. 春节必看的五个Asp.net源码!
  9. FLEX Tree动态获得信息时遇到的问题总结
  10. jmeter学习指南之快速玩转16个逻辑控制器
  11. Linq简单语句记录
  12. easyui焦点离开事件的解决方案
  13. 实战 | 使用Slack、Docker来打造你的运维机器人
  14. SpringAop+Mybatis 实现动态切换数据库操作
  15. datax 执行流程分析
  16. python - 安装/解释器/变量
  17. GitHub上整理的一些工具
  18. 探索性测试--极限测试法
  19. android手机连不上wifi密码,修改wifi密码后手机连不上_修改wifi密码后手机不能上网-192路由网...
  20. Python数据分析之用户留存

热门文章

  1. 微信公众号带场景参数的二维码生成与使用?
  2. 滴滴出行2016校招编程题
  3. Zynq FPGA低时延H.264设计方案(编码+解码< 1ms)
  4. safari隐私模式下LocalStorage无法使用
  5. 再读图灵奖得主Brooks 没有银弹 什么是卓越的设计者
  6. 《算法图解》读书笔记—像小说一样有趣的算法入门书
  7. AIRPLAY镜像音频数据的处理
  8. 【计算机算法】递归——打印旋转方阵(正转及逆转)
  9. Windos环境下kafka配置启动Zookeeper时,报错:Invalid config, exiting abnormally.
  10. 「备战春招/秋招系列」程序员的简历就该这样写