最近项目比较忙,在做完了一个在线问诊的项目后,想给大家分享下其中用到的,但是百度上资料又比较少的技术
需求背景:医生需要和患者在线沟通,我们已经做完了基于融云的app原生聊天室开发,但是需要在开发出一套web版的聊天室,这样可以嵌入到其他公司的app里面
技术方案:我们选用了vue作为前端开发框架,使用localstorage作为聊天记录的缓存,实现了医生和患者聊天的需求
搭建:
index.html引入融云资源
<script src="https://cdn.ronghub.com/RongIMLib-2.5.0.min.js"></script> <script src="https://cdn.ronghub.com/Libamr-2.2.5.min.js"></script> <script src="https://cdn.ronghub.com/RongIMVoice-2.2.6.js"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
2. 初始化融云(token要写接口去获取),需要注意的是,要想聊天,两个端appid必须一致
//初始化融云 initRongCloud() { var appkey = this.appkey var token = this.token console.log("开始初始化") const _this = this if (!appkey || !token) { alert('appkey 和 token 不能为空') } else { init({ appkey: appkey, token: token }, this.addPromptInfo) } }
3.使用融云的方法来监听收到的消息,举个例子,这一块融云的文档写的很详细
// 文本消息 SET_ANSWER_TXT (state, playload) { let say = { type: 'txt', css: 'left', txt: playload.content.content, headImg: playload.content.user.portrait, msgId: playload.messageId, targetId: playload.targetId, Name: playload.content.user.name, sendTime: playload.sentTime } if (state.targetId === playload.targetId) { state.answer.push(say) // 保存历史聊天记录 let tmp = JSON.stringify(state.answer) localStorage.setItem(state.targetId, tmp) } },
4. 使用vue的watch和computed来检测数据的变动,使用store来存储每次发送的消息,聊天界面的聊天信息展示是遍历的store中的数据
computed的定义
当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。
watch的定义
如果watch监测的是一个对象的话,直接使用watch是不行的,此时我们可以借助于computed计算属性来完成
mounted() { //融云初始化(获取token,初始化融云实例) this.start() this.$refs.content.scrollTop = this.$refs.content.scrollHeight; }, watch: { answer() { this.$nextTick(() => { const list = document.getElementById('test') //医生回复消息集合 var answer_doctor = this.$store.state.answer console.log(answer_doctor) if(answer_doctor!==null) { let len = answer_doctor.length - 1 //医生发送咨询结束消息 if (answer_doctor[len].txt !== undefined && answer_doctor[len].txt === '在线咨询已结束') { console.log('在线咨询已结束') document.getElementById('send').style.display = 'none' document.getElementById('topTime').style.display = 'none' document.getElementById('rebuy').style.display = 'flex' }else if(answer_doctor[len].txt !== undefined && answer_doctor[len].txt === '医生已退回咨询,问诊费用将原路返回') { console.log('医生已退回咨询') document.getElementById('send').style.display = 'none' document.getElementById('topTime').style.display = 'none' }else if(answer_doctor[len].txt !== undefined && answer_doctor[len].txt.startsWith('您的在线咨询结束时间已延长')) { document.getElementById('rebuy').style.display = 'none' document.getElementById('send').style.display = 'flex' document.getElementById('topTime').style.display = 'flex' } } document.documentElement.scrollTop = list.scrollHeight //如不行,请尝试-> list.scrollTop = list.scrollHeight }) } },
聊天页面的展示(分左右两块,左面是接受的消息,右边是发送的消息,这是代码是发送的消息)
<div v-if="(data.targetId === this.$store.state.targetId) && (data.css === 'right')" class="right" :id="data.msgId"> <van-image class="item-media" round fit="cover" :src="data.headImg" /> <div class="item-inner"> <!-- 文本消息 --> <!-- <span class="showtime">{{func(data.sendTime)}}</span> --> <div class="item-subtitle">{{data.Name}}</div> <div class="item-title-row" v-if="data.type == 'txt'"> <div class="item-title txt">{{data.txt}}</div> </div> <!-- 图片消息 --> <div class="item-title-row showImg" v-if="data.type == 'image'"> <van-image :src="data.txt" fit="fill" @click="imgShow(data.msgId,1)"/> </div> </div> </div>
4.使用store.js 来存储消息,当收到消息的时候,将信息存到内存中即store.js定义的数组中(store中定义的对象如果页面不刷新就不会丢失),每次当收到消息或者发送消息的时候,存到localstorge里面,可以看上面那段代码
参考源码:https://github.com/BoHongtao/vue-rongcloud
参考教程: https://juejin.im/post/5d38677af265da1b88121f72