前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >uni-app+php+workman实现简单聊天功能之交互实现(会话列表)

uni-app+php+workman实现简单聊天功能之交互实现(会话列表)

作者头像
切图仔
发布2022-09-08 16:29:46
9200
发布2022-09-08 16:29:46
举报
文章被收录于专栏:生如夏花绚烂生如夏花绚烂

前面介绍了【Laravel中Websocket基本使用(Workerman)】 基于workman的基础上实现了【uni-app+php+workman实现简单聊天功能之API开发】【uni-app+php+workman实现简单聊天功能之聊天模块封装】 接下来完成前后端交互,本文只介绍主要页面和主要代码 我们涉及到的页面有主要两个

  1. 消息列表页
  2. 消息详情页

msg.vue

代码语言:javascript
复制
<template>
    <view>
        <!-- 消息列表 -->
        <template v-if="list.length>0">
            <block v-for="item,index in list" :key="index">
                <msg-list :item="item" :index="index"></msg-list>
            </block> 
        </template>
        <view>
<template>
代码语言:javascript
复制
<script>
    import msgList from "@/components/msg/msg-list.vue"
    export default {
    components:{msgList},
    data() {
        return {
            firstload:false,
            show:false,
            list:[]
        }
    },
    onShow(){
        //获取消息列表
        this.getdata()
        console.log(this.list)
    },
    onLoad() {
        //监听消息
        uni.$on('UserChat',data=>{
            //将最新消息置顶更新
            let index = this.list.findIndex(val=>{
                return val.userid === data.from_id;
            });
            //如果当前会话存在则更新时间、内容、未读数,并进行置顶
            if(index!==-1){
                this.list[index].data = data.data
                this.list[index].time = data.time
                this.list[index].noreadnum++;
                //置顶
                this.list = this.$chat.__toFirst(this.list,index)
                return

            }
            //如果当前会话不存在--新消息 则将当前消息追加到消息列表最前面
            let obj = this.$chat.__format(data,{type:"chatlist"});
            obj.noreadnum=1;
            this.list.unshift(obj);
        })
    },
    methods: {
        getdata(){
            try{
                let userid = User.userinfo.id;
                if(!userid) return this.firstload = true;
                this.list = [];
                let list = uni.getStorageSync('chatlist'+userid)//获取消息列表
                list = list?JSON.parse(list):[];
                this.list = list;//添加到消息列表
            }catch(e){
                uni.showToast({
                    title: '加载失败~',
                    icon:'none'
                });
            }
            this.firstload = true;

        }

...

在页面初始化的时候,我们调用getdata获取消息列表数据,从本地存储中取到,因为我们在收到消息的时候会将其存储到本地存储,并进行未读消息的统计。可参照前面【uni-app+php+workman实现简单聊天功能之聊天模块封装】 同时本页面还监听消息事件,当收到消息的时候,对最新消息进行置顶 本页面使用了msgList组件

代码语言:javascript
复制
<template>
        <view class="flex align-center p-2 border-bottom animate__animated animate__fast animate__fadeIn" @click="open">
            <image :src="item.userpic" style="height: 80rpx;width: 80rpx;" 
            class="rounded-circle mr-2">
            </image>
            <view class="flex flex-column flex-1">
                <view class="flex align-center justify-between">
                    <text class="font-md">{{item.username}}</text>
                    <text class="font font-sm text-secondary">{{item.time}}</text>
                </view>
                <view class="flex align-center justify-between">
                    <text class="text-secondary text-ellipsis" style="max-width: 500rpx;">
                        {{item.data}}
                    </text>
                    
                    <uni-badge :text="getItemNoreadnum" type="error" v-if="getItemNoreadnum"></uni-badge>
                </view>
            </view>
        </view>
</template>

<script>
    import uniBadge from "@/components/uni-ui/uni-badge/uni-badge.vue"
    export default{
        components:{
            uniBadge
        },
        //接受聊天数据
        props:['item'],
        methods:{
            open(){
                
                uni.navigateTo({
                    "url":"../../pages/user-chat/user-chat?userinfo="+JSON.stringify({
                        userid:this.item.userid,
                        username:this.item.username,
                        userpic:this.item.userpic
                    })
                })
                this.$chat.Read(this.item)//更新未读数据   
            }
            
        },
        computed:{
            getItemNoreadnum(){
                return this.item.noreadnum
            }
        }
    }
    ...

该组件主要实现列表消息渲染和跳转操作,消息未读清零 当消息列表被点击时,会跳转到消息详情页并传递对方用户的相关参数,在进行调用chat模块的Read进行消息清零操作 效果图展示

user-chat

代码语言:javascript
复制
<template>
    <view>
        <!-- 聊天列表 -->
        <scroll-view scroll-y="true" 
        style="position: absolute;left:0;top:0;right:0;bottom: 100rpx;"
        :scroll-into-view="scrollInfo" scroll-with-animation>
            <block v-for="item,index in list" :key="index">
                <view :id="'chat'+index">
                    <!-- 头像一直左上方 | 左边 | 如果不是第一条消息传入上一次消息时间-->
                    <user-chat-list  v-if="!item.isme" :item="item" :index="index " :pretime="index>0?list[index-1].create_time:0"></user-chat-list>
                    
                </view>
                <!-- 右边 -->
                <view v-if="item.isme" class="flex align-start px-2" style="flex-direction: row-reverse;">
                    <image :src="item.userpic" style="width:100rpx;height:100rpx" class="rounded-circle">
                        <view class="bg-light p-2 rounded mx-2" style="min-width: 200rpx;max-width: 400rpx;">
                            {{item.data }}{{item.userid}}
                        </view>
                    </image>
                </view>
            </block>
            
        </scroll-view>
        <bottom-input @submit="submit"></bottom-input>
    </view>
</template>
代码语言:javascript
复制
export default {
        components:{
            userChatList,bottomInput
        },
        data() {
            return {
                scrollInfo:"",
                scrollH:500,
                focus:true,
                loadtext:'加载更多',
                list:[]
            }
        },
        onLoad(e){
             //获取发送方用户信息
             let userinfo = JSON.parse(e.userinfo)
             //没有该用户
             if(!userinfo.userid){
                 uni.showToast({
                     title: '该用户不存在',
                    icon:'none'
                 });
                 return uni.navigateBack({
                     delta:1
                 })
             }
             //设置当前聊天对象
             this.$chat.CurrentToUser = {
                 userid:userinfo.userid,
                 username:userinfo.username,
                 userpic:userinfo.userpic
             }
             //修改导航标题
             uni.setNavigationBarTitle({
                 'title':userinfo.username
             })
        },//退出聊天的时候
        onUnload() {
            //初始化聊天对象
            this.$chat.CurrentToUser = {
                userid:0,
                username:"",
                userpic:"",
            }
        },
        onReady(){
            this.__init()
        },
        methods: {
            //接受聊天数据(首次只获取10条数据)
            async getdata(isall = false){
                try{
                    let key = 'chatdetail_'+this.User.userinfo.id+'_'+this.$chat.CurrentToUser.userid;
                    //获取聊天记录
                    let list = uni.getStorageSync(key);
                    // console.log(list)
                    list = list?JSON.parse(list):[];
                    //首次加载10条
                    if(!isall && list.length>10){
                        return this.list = list.splice(0,10);
                    }
                    //加载剩下的数据
                    this.list = list;
                    this.loadtext = '';
                    
                    
                }catch(e){
                    uni.showToast({
                        title:'加载失败',
                        icon:'none'
                    })
                }
            },
            submit(data){
                //发送消息
                let obj = this.$chat.Send({'type':'text','data':data,'isme':true});
                console.log(obj)
                this.$.post('chat/send',{
                     'to_id':this.$chat.CurrentToUser.userid,
                    'from_userpic':'https://cdn.learnku.com/uploads/images/201710/14/1/s5ehp11z6s.png',
                    'type':'text',
                    'data':data
                },{
                    header: {
                        'Accept':'application/json',
                        'Authorization':'Bearer '+uni.getStorageSync('access_token')
                    }
                }).then(res=>{
                    console.log(res)
                    console.log('发送完毕')
                    
                    //错判断
                     //成功处理
                     // return this.resultUserBind(res.data.data)
                })
                
                this.list.push(obj)
                
                this.pageToBottom()
            },
            //滚动底部
            pageToBottom(){
                let lastIndex = this.list.length-1
                if(lastIndex<0)return;
                this.scrollInfo = 'chat'+lastIndex
            },
            //初始化参数
            __init(){
                //获取窗口消息
                try{
                    const res = uni.getSystemInfoSync();
                    this.scrollH = res.windowHeight-uni.upx2px(101);
                    
                }catch(e){
                    
                }
                //获取聊天历史记录
                this.getdata();
                //至于底部
                this.pageToBottom()
                //监听消息
                uni.$on('UserChat',data=>{
                    this.list.push(this.$chat.__format(data,{
                        type:'chatdetail',
                        isme:false,
                        olddata:this.list
                    }));
                this.pageToBottom()
                console.log('监听到数据')
                // console.log(data)
                })
            }
        }
        
    }
</script>

消息详情页加载的时候首先对聊天用户进行了初始化,保存在chat模块,然后调用初始化函数__init()该函数用于

  1. 设置内容滚动高度
  2. 获取聊天记录
  3. 监听消息,对消息存储(chat模块),最新消息展示

当发送消息时,调用chat模块的Send函数,进行数据格式,数据存储等 然后在发送ajax与服务器进行交互 服务端拿到数据后首先判断接收方用户是否在线,如果在线则转发,不在线则存储到缓存

代码语言:javascript
复制
public function send(ChatRequest $request){
        // 1. 验证数据是否合法
        // 2. 组织数据

        $data = $this->resdata($request);
        // return response()->json($data);
        $to_id = $request->to_id;
        // 3. 验证对方用户是否在线
        if (Gateway::isUidOnline($to_id)) {
            // 直接发送
            Gateway::sendToUid($to_id,json_encode($data));
            // 写入数据库
            // 返回发送成功
            return $this->showResCodeWithOutData('ok');
        }
        // 不在线,写入消息队列
        // 获取之前消息
       
        $Cache = Cache::get('userchat_'.$to_id);
        if (!$Cache || !is_array($Cache)) $Cache = [];
        $Cache[] = $data;
        // 写入数据库
        // 写入消息队列(含id)
        Cache::set('userchat_'.$to_id,$Cache);
        return $this->showResCodeWithOutData('ok');
    }

效果展示

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档