美文网首页
vue h5页面 使用第三方聊天(环信集成web端)

vue h5页面 使用第三方聊天(环信集成web端)

作者: 鬼魅汐 | 来源:发表于2021-12-09 14:40 被阅读0次

    项目需求: 实时聊天,发送文字,图片,以及文件 (该项目使用vant + vue 搭建)

    首先,聊天也是我第一次写,之前只是维护,第一次采取了自己搭建的,源于后台协商socket-io 服务器比较难搭建,本着时间紧任务重的原因,最后果断采取了第三方聊天,在网上百度了好多资料,最后还是决定使用环信。官方文档属实是不想看,后来就疯狂百度,发现总是差一下,最后还是自己摸索吧。

    [环信官方文档]: web集成官方文档

    第一步: 需要注册环信即时通信云获得appkey,注册账号之后登录环信后台创建应用就可以得到appkey

    第二步: 在vue项目中安装插件 npm install easemob-websdk --save
    在main.js里引入 import websdk from 'easemob-websdk'

    第三步: 在util里新建一个文件夹WebIM,文件夹下新建WebimConfig.js

    const config = {
        xmppURL: 'im-api.easemob.com',            // xmpp Server地址,对于在console.easemob.com创建的appKey,固定为该值
        // apiURL: 'http://a1.easemob.com',          // rest Server地址,对于在console.easemob.com创建的appkey,固定为该值
        apiURL: (location.protocol === 'https:' ? 'https:' : 'http:') + '//a1.easemob.com',
        appkey: '678659375498374#demo',        // App key
        https : false,                            // 是否使用https
        isHttpDNS: true,                         //防止DNS劫持从服务端获取XMPPUrl、restUrl
        isMultiLoginSessions: false,              // 是否开启多页面同步收消息,注意,需要先联系商务开通此功能
        isAutoLogin: true,  
        isWindowSDK: false,
        isSandBox: false,                      // 自动出席,(如设置为false,则表示离线,无法收消息,需要在登录成功后手动调 用conn.setPresence()才可以收消息)
        isDebug: false,                           // 打开调试,会自动打印log,在控制台的console中查看log
        autoReconnectNumMax: 2,                   // 断线重连最大次数
        autoReconnectInterval: 2,                 // 断线重连时间间隔
        isWebRTC: (/Firefox/.test(navigator.userAgent) || /WebKit/.test(navigator.userAgent)) && /^https\:$/.test(window.location.protocol),
        heartBeatWait: 4500,                       // 使用webrtc(视频聊天)时发送心跳包的时间间隔,单位ms
        msgStatus: true,
        delivery: true,                            // 是否发送已读回执
        read: true,
        saveLocal: false,                      
        encrypt: {
            type: 'none'
        },
        useOwnUploadFun: true     //发送url图片消息
    }
    
    export default config;
    

    第四步: 将WebimConfig.js这个文件在main.js里引入
    import webimconfig from './util/WebIM/WebimConfig'

    //vue集成通信
    import websdk from 'easemob-websdk'
    import webimconfig from './util/WebIM/WebimConfig'
    // 环信
    let WebIM = window.WebIM = websdk;
    WebIM.config = webimconfig;
    // 环信实例
    var conn = WebIM.conn = new WebIM.connection({
      appKey: WebIM.config.appkey,
      isHttpDNS: WebIM.config.isHttpDNS,
      isMultiLoginSessions: WebIM.config.isMultiLoginSessions,
      https: WebIM.config.https,
      url: WebIM.config.xmppURL,
      apiUrl: WebIM.config.apiURL,
      isAutoLogin: true,
      heartBeatWait: WebIM.config.heartBeatWait,
      autoReconnectNumMax: WebIM.config.autoReconnectNumMax,
      autoReconnectInterval: WebIM.config.autoReconnectInterval,
      isStropheLog: WebIM.config.isStropheLog,
      delivery: WebIM.config.delivery
    })
    var optionsIm = {
      apiUrl: WebIM.config.apiURL,
      user: '', //换成自己申请的账号就行,密码也需要换  
      pwd: '',
      appKey: WebIM.config.appkey,
      success: function (res) {
        console.log('链接服务器正常')
      },
      error: function (err) {
        console.log(err)
      }
    }
    Vue.prototype.$WebIM = WebIM;
    Vue.prototype.$imconn = conn
    Vue.prototype.$imoption = optionsIm;
    

    第五步: 我这个项目没有注册,我直接在登录里拿到账号密码,存储起来,传到后台,并入环信。

    //测试账号
            this.$imoption.user = this.login_userName
            this.$imoption.pwd = this.login_password
            //存储账号密码
            this.saveGetUserInfo({name: this.login_userName, word: this.login_password })
            this.$imconn.open(this.$imoption);
            // 监听回调
            this.$imconn.listen({
              onOpened: function() {
                console.log("用户已上线");
              },
              onClosed: function() {
                console.log("用户下线");
              },
            });
    

    第六步: 在聊天页发送(接收)文本消息,图片,以及文件

    <template>
        <div id="ChatInterface">
            <van-nav-bar :title='title'
                         :fixed=true
                         :border=false
                        @click-left="onClickLeft"
                         left-arrow
                         style="height:0.88rem" />
    
            <div class="box">
                <div class="content">
                    <van-divider v-if="charList.length == 0" :style="{ color: '#000', borderColor: '#ccc', padding: '0 16px',fontSize: '.28rem',fontWeight: '300' }">暂无聊天记录</van-divider>
                    <div v-else >
                        <ul v-for="(item,index) in charList" :key="index">
                            <li :class="userInfo.member_id != item.member_id ? 'msg-other': 'msg-me'" >
                                <p v-if="item.if_show_time">{{item.insert_time_date}}</p>
                                <div class="message">
                                    <div class="message_i">
                                        <img class="message_image" :src="userInfo.member_id != item.member_id ? item.avatar: userInfo.member_avatar" alt="">
                                    </div>
                                    <!-- 文本 -->
                                    <div class="content" v-if="item.content">{{item.content}}</div>
                                    <!-- 图片 -->
                                    <img class="image_con" v-if="item.image" :src="item.image" alt="">
                                    <!-- 文件 -->
                                    <div class="document" v-if="item.document" @click="godownFile(item.document)">
                                        <div class="doc_one">
                                            <p class="file_title">{{item.fileName}}</p>
                                            <p class="file_size"></p>
                                        </div>
                                        <img class="file_image" :src="downFile" alt="">
                                    </div>
                                </div>
                            </li>
                        </ul>
                    </div>
                </div>
    
                <div class="Bottom">
                    <div class="replyInput">
                        <img :src="images.comment" />
                        <van-field
                                v-model="currentValue"
                                rows="1"
                                autosize
                                ref="testArea"
                                type="textarea"
                                placeholder="发消息..."
                        />
                    </div>
                    <div class="sendclick" v-if="currentValue?false:true">
                        <!-- 发送文件 -->
                        <van-uploader class="save" :after-read="afterRead" accept=".txt, .pdf, .doc, .docx, .xls, .xlsx">
                            <img :src="images.file" />
                        </van-uploader>
                        <!-- 发送图片 -->
                        <van-uploader class="save" :after-read="afterPicture" accept="image/*">
                            <img :src="images.picture" />
                        </van-uploader>
                    </div>
                    <div @click="submit" v-if="currentValue?true:false" class="send">发送</div>
    
                </div>
            </div>
    
    
            <!--路由的出口-->
            <transition name="router-slider"
                        mode="out-in">
                <router-view></router-view>
            </transition>
    
        </div>
    
    </template>
    
    <script type="text/javascript">
    import { Toast } from 'vant';
    import { memberMessageList,memberLeaveMessage,memberChatFiles } from '../../../api/notificationChat'
    import ChatMessage from './ChatMessage.vue'
    import { mapState } from 'vuex'
    import axios from "axios";
        export default {
            name: "chatInterface",
            data(){
                return{
                    currentValue:'',//输入内容
                    title: this.$route.query.member_name ? this.$route.query.member_name : '聊天名称',
                    messageBy_id: this.$route.query.by_id ? this.$route.query.by_id : '',   //聊天发送消息传入聊天列表页的by_id
                    charList:[],
                    fileImg:'',   //文件
                    $imconn: {},
                    $imoption: {},
                }
            },
            created(){
                //声明调用
                this.$imconn = this.$imconn;
                this.$imoption = this.$imoption;
                this.loginWebIM()
    
                //调用聊天记录接口
                that.messageList(this.detailId,this.chatId)
                
            },
            watch:{
                //监听接收页面传过来的动态值
                '$route.query': function(){
                    //判断聊天窗口的title是否为空
                    this.title = this.$route.query.member_name;
                    this.messageBy_id = this.$route.query.by_id
                    if (this.source == 1) {
                        //调用聊天记录接口
                        this.messageList('',this.chatId)
                    }else if(this.source == 2){
                        this.messageList(this.detailId,'')   //获取聊天记录
                    }
                },
    
            },
            //进入页面滑动到底部
            updated(){
                this.scrollToBottom();
            },
            methods: {
                //登录环信
                loginWebIM(){
                    //拿到存储后的账号密码赋值
                    this.$imoption.user = this.name
                    this.$imoption.pwd = this.word
                    this.$imconn.open(this.$imoption);
                    // open方法,传入挂载在vue实例上的配置对象
                    let _this = this;
                    this.$imconn.listen({
                        onOpened: function (message) {
                            console.log('用户已接收') // 控制台打印出这句证明连接成功啦
                        },
                        onClosed: function (message) {
                            console.log('用户未接收')
                        },
                        // 集成收到文本信息方法
                        onTextMessage: function ( message ) {
                            // console.log(message)
                            _this.charList.push({
                                avatar: message.ext.avatar,
                                content: message.data,
                                imgUrl: message.ext.url,
                                member_id: message.ext.member_id,
                                insert_time_date: message.ext.insert_time_date,
                                insert_time: message.ext.insert_time,
                                member_name: message.ext.member_name
                            });
                        },
                        //收到图片消息
                        onPictureMessage: function ( message ) {
                            // console.log(message)
                            _this.charList.push({
                                avatar: message.ext.avatar,
                                member_id: message.ext.member_id,
                                insert_time_date: message.ext.insert_time_date,
                                insert_time: message.ext.insert_time,
                                member_name: message.ext.member_name,
                                image: message.ext.url
                            });
                        },
                        //收到文件消息
                        onFileMessage: function ( message ) {
                            // console.log(message)
                            _this.charList.push({
                                avatar: message.ext.avatar,
                                member_id: message.ext.member_id,
                                insert_time_date: message.ext.insert_time_date,
                                insert_time: message.ext.insert_time,
                                member_name: message.ext.member_name,
                                document: message.ext.fileUrl,
                                fileName:message.ext.fileName,
                                fileLength: message.ext.fileLength
                            });
                        },    
    
                    })
                },
                // 返回
                onClickLeft () {
                    this.$router.back();
                },
                //文件按钮
                afterRead(file) {
                    // 此时可以自行将文件上传至服务器
                    let formData = new FormData()
                    formData.append('file',file.file)
                    formData.append('id',this.detailId)
                    formData.append('chat_id',this.chatId)
                    formData.append('image','')
                    // 添加请求头
                    memberChatFiles (formData).then(res => {
                        if (res.data.status == 1) {
                            let filedata = res.data.data
                            var id = this.$imconn.getUniqueId();        // 生成本地消息id
                            var msg = new WebIM.message('file', id);        // 创建文件消息
                            var time = +new Date()
                            let _this = this;    // 创建文本消息
                            msg.set({
                                file: file,
                                chatType: 'singleChat',    //单聊
                                ext: {          //ext扩展   将参数可放置这里
                                    time: time,
                                    fileUrl: filedata.document,
                                    fileName: filedata.fileName,
                                    fileLength: file.file.size,
                                    avatar: filedata.avatar,
                                    member_id: filedata.member_id,
                                    member_name: filedata.member_name,
                                    insert_time_date: filedata.insert_time_date,
                                    insert_time: filedata.insert_time
                                },
                                to: this.title,  // 接收消息对象 (指的是跟你会话的人存入环信的账号)
                                onFileUploadError: function () {      // 消息上传失败
                                    console.log('onFileUploadError');
                                },
                                onFileUploadProgress: function (e) { // 上传进度的回调
                                    console.log(e)
                                },
                                onFileUploadComplete: function () {   // 消息上传成功
                                    console.log('文件上传成功');
                                },
                                success: function () {                // 消息发送成功
                                    console.log('文件已发送')
                                    _this.charList.push({            //将数据push数组内,展示在页面(指自己发送的这方)
                                        avatar: filedata.avatar,
                                        member_id: filedata.member_id,
                                        insert_time_date: filedata.insert_time_date,
                                        insert_time: filedata.insert_time,
                                        member_name: filedata.member_name,
                                        document: filedata.document,
                                        fileName: filedata.fileName
                                    });
                                    _this.keepbottom();
                                },
                                fail: function(e){
                                    console.log("Fail");              //如禁言、拉黑后发送消息会失败
                                },
                                flashUpload: WebIM.flashUpload,
                            });
                            msg.body.chatType = "singleChat";
                            this.$imconn.send(msg.body);
                        }else{
                            Toast(res.message)
                        }
                    })
                },
                //图片
                afterPicture(file){
                    let formData = new FormData()
                    formData.append('file','')
                    formData.append('id',this.detailId)
                    formData.append('chat_id',this.chatId)
                    formData.append('image',file.file)
                    // 添加请求头
                    memberChatFiles (formData).then(res => {
                        if (res.data.status == 1) {
                            this.fileImg = res.data.data.image
                            let imagedata = res.data.data
                            var id = this.$imconn.getUniqueId();        // 生成本地消息id
                            var msg = new WebIM.message('img', id);        // 创建图片消息
                            var time = +new Date()
                            let _this = this;    // 创建文本消息
                            msg.set({
                                body:{
                                    type: 'image',
                                    url: this.fileImg,
                                    filename: file.file.name,
                                    filetype: file.file.type
                                },
                                ext: {
                                    time: time,
                                    url: this.fileImg,
                                    avatar: imagedata.avatar,
                                    member_id: imagedata.member_id,
                                    insert_time_date: imagedata.insert_time_date,
                                    insert_time: imagedata.insert_time,
                                    member_name: imagedata.member_name
                                },
                                to: this.title,  // 接收消息对象
                                success: function(){
                                    console.log('图片已发送')
                                    _this.charList.push({
                                        avatar: imagedata.avatar,
                                        image: imagedata.image,
                                        member_id: imagedata.member_id,
                                        insert_time_date: imagedata.insert_time_date,
                                        insert_time: imagedata.insert_time,
                                        member_name: imagedata.member_name
                                    });
                                    _this.keepbottom();
                                },
                                flashUpload: WebIM.flashUpload 
                            });
                            msg.body.chatType = "singleChat";
                            this.$imconn.send(msg.body);
                        }else{
                            Toast(res.data.message)
                        }
                    })
                },
                //获取聊天记录
                messageList(id,chat_id){
                    //获取聊天记录
                    memberMessageList(id,chat_id).then(res => {
                        // console.log(res)
                        if(res.status == 1){
                            this.charList = res.data;
                        }
                        if(res.status == '-1'){
                            Toast(res.message)
                            this.$router.go(-1)
                        }
                    })
                },
                getMessage (item, index) {
                    this.getTime(item, index)
                    return this.charList[index]
                },
                //处理时间5分钟内不展示
                getTime (item, index) {
                    let time = item.insert_time
                    //定义一个if_show_time默认false  不显示
                    this.charList[index]['if_show_time'] = false
                    if (index) {
                        if (Math.abs(this.charList[index - 1]['show_time'] - time) > 30) {
                            this.charList[index]['show_time'] = time
                            this.charList[index]['if_show_time'] = true
                        } else {
                            this.charList[index]['show_time'] = this.charList[index - 1]['show_time']
                        }
                    } else {
                        this.charList[index]['show_time'] = time
                        this.charList[index]['if_show_time'] = true
                    }
                },
                //进入页面滑动到底部
                scrollToBottom() {
                    this.$nextTick(() => {
                        var container = this.$el.querySelector('.content');
                        //content
                        container.scrollTop = container.scrollHeight
                    })
                },
                //发送
                submit(){
                    if (this.currentValue=='') {
                        Toast('请填写内容')
                        return
                    }
                    memberLeaveMessage(this.detailId,this.messageBy_id,this.currentValue).then(res => {
                        // console.log(res)
                        if (res.status == 1) {
                            let receivemsg = res.data
    
                            var id = this.$imconn.getUniqueId();        // 生成本地消息id
                            var msg = new WebIM.message('txt', id);
                            var time = +new Date()
                            let _this = this;    // 创建文本消息
                            //生成本地消息id
                            msg.set({
                                msg: this.currentValue, // 消息内
                                from: this.name,
                                to: this.title, // 接收消息对象(用户id)
                                roomType: true,
                                // ext表示拓展对象,这个会随着你发送而发送过去,你接收时同样可以拿到这个数据
                                ext: {
                                    time: time,
                                    avatar: receivemsg.avatar,
                                    member_id: receivemsg.member_id,
                                    insert_time_date: receivemsg.insert_time_date,
                                    insert_time: receivemsg.insert_time,
                                    member_name: receivemsg.member_name
                                },
                                success: function(id, serverMsgId) {
                                    //  追加本地缓存处理
                                    // console.log(msg);
                                    //发送成功数据
                                    console.log("消息发送成功");
                                    //把发送者的头像和文本数据push到数组中在页面上展示
                                    _this.charList.push({
                                        avatar: receivemsg.avatar,
                                        content: msg.value,
                                        member_id: receivemsg.member_id,
                                        insert_time_date: receivemsg.insert_time_date,
                                        insert_time: receivemsg.insert_time,
                                        member_name: receivemsg.member_name
                                    });
                                    
                                    _this.keepbottom();
                                },
                                fail: function(e) {
                                    // 失败原因:
                                    // e.type === '603' 被禁言
                                    // e.type === '605' 群组不存在
                                    // e.type === '602' 不在群组或聊天室中
                                    // e.type === '504' 撤回消息时超出撤回时间
                                    // e.type === '505' 未开通消息撤回
                                    // e.type === '506' 没有在群组或聊天室白名单
                                    // e.type === '501' 消息包含敏感词
                                    // e.type === '502' 被设置的自定义拦截捕获
                                    // e.type === '503' 未知错误
                                    console.log("消息发送失败");
                                }
                            });
                            msg.body.chatType = "singleChat";
                            this.$imconn.send(msg.body);
    
                            this.currentValue = ''
                        }
                    })
                },
                godownFile(fileUrl){
                    window.open(fileUrl);
                }
    
            },
    
        }
    </script>
    
    到此就是完整的聊天页面了,可以进行实时聊天发送图片以及文件,有不完善或者更好的方案的可以跟我交流,后续如果有语音,视频,推送等功能会继续更新…

    相关文章

      网友评论

          本文标题:vue h5页面 使用第三方聊天(环信集成web端)

          本文链接:https://www.haomeiwen.com/subject/uteffrtx.html