websoket

作者: 为了_理想 | 来源:发表于2021-09-02 15:12 被阅读0次
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <link rel="stylesheet" href="/Public/Css/imWeb.css">
        <title></title>
        <style>
          [v-cloak] {
           display: none;
         }
        .imWeb_backImg{ 
        width: 20px;
        }
        </style>
    </head>
    
    <body>
    
        <div class="imWeb" v-cloak>
            <div class="imWeb_header">
                <header class="imWeb_kefu_header">
                    <div class="imWeb_header_left" @click="callBack">
                        <img v-if="userInfo.client!='miniapp'" class="imWeb_backImg" src="/Public/images/choseIfm.png" alt="">
                    </div>
                    <div>
                        {{activeObj.nickname}}
                        <span class="on_line_status">{{on_line ? '在线' : '离线'}}</span>
                    </div>
                    <div class="imWeb_header_right" >
                        <img @click="clickKehu"  ref="kehuMenuImg" class="imWeb_kehuImg" v-if="kefuList.length>1"
                            :src="isNextOpen ? '/Public/images/imWeb_kehuMenu.png' : '/Public/images/imWeb_ColorKehuMenu.png'"
                            alt="">
                    </div>
                </header>
            </div>
    
            <div class="imWeb_main">
                <div ref="imWebPopup" v-if="isShowPopUp">
                    <div ref="popup" class="imWeb_popup">
                        <div class="imWeb_popup_right_list" ref="imWeb_popup_right_list">
                                <div @click="clickehuList(item, index)"
                                    :class="item.is_chose ? 'imWeb_popup_right_list_box_active' : 'imWeb_popup_right_list_box'"
                                    v-for="(item,index) in kefuList" :key="index">
                                    <div class="imWeb_popup_right_list_left">
                                        <img style="border-radius: 40%;" src="/Public/images/kefu.jpg" alt="">
                                    </div>
                                    <div class="imWeb_popup_right_list_right">
                                        <div>{{item.nickname}}</div>
                                        <div class="imWeb_popup_right_list_right_messge">
                                            <span style="color:red" v-if="item.has_new_msg">收到新信息</span>
                                            {{item.content}}
                                        </div>
                                    </div>
                                </div>
                            </div>
                    </div>
                </div>
    
                <div class="imWeb_main_center" ref="imWeb_main_center">
                    <div class="chatPage_right_main" ref="chatPage_right_main_ref" @click="closeMainBox">
                        <!-- @click="closeFy(item,index)" -->
                        <div class="chatPage_messge_main_box" ref="chatPage_right_main_ref_for" v-for="(item,index) in nowMsg" :key="index">  
    
                           
                            <div class="chatPage_right_main_left" v-if="item.is_main == 2" >
                                <div class="chat_header_box">
                                    <img style="border-radius:35%;" src="/Public/images/kefu.jpg" alt="">
                                </div>
                                <div style="max-width: 55%;">
                                    <div class="message" @click.stop="translate(item,index)" v-if="item.type == 0">
                                        {{item.content}}
                                    </div>
                                    <div v-if="item.translation_content">
                                        <div class="translate_box_left_right">
                                            {{item.translation_content}}
                                        </div>
                                    </div>
                                </div>
    
                                <div class="message" v-if="item.type == 1">
                                    <img @click="clickImages(item)" style="width:60px;user-select:none;" :src="item.content"
                                        alt="">
                                </div>
                                <div ref="translate_box" class="translate_box" v-if="activeFy == index && clickTranslate">
                                    <div class="translate_box_main">
                                        <div class="translate_box_left" @click.stop="translateItem(item,index,'en')">
                                            <div style="margin-top:6px;user-select:none;">
                                                <img src="/Public/images/imWeb_english.png" alt="">
                                            </div>
                                            中=>英
                                        </div>
                                        <div class="translate_box_left" @click.stop="translateItem(item,index,'zh')">
                                            <div style="margin-top:6px;user-select:none;">
                                                <img src="/Public/images/imWeb_chinese.png" alt="">
                                            </div>
                                            en=>zh
                                        </div>
                                    </div>
                                </div>
                            </div>
    
    
                            <div class="chatPage_left_main_left" v-if="item.is_main == 1">
                                <div class="chat_header_box_right">
                                    <div class="messageRight" v-if="item.type == 0">
                                        <div v-if="item.is_upload == 1">
                                            <img style="width:60px;user-select:none;" @click="clickImages(item)"
                                                :src="item.content" alt="">
                                        </div>
                                        <div v-else>
                                            {{item.content}}
                                        </div>
                                    </div>
                                    <div class="messageRight" v-if="item.type == 1">
                                        <img style="width:60px;user-select:none;" @click="clickImages(item)"
                                            :src="item.content" alt="">
                                    </div>
                                </div>
                                <div class="messageRight_headerImg">
                                    <img src="/Public/images/kehu.png" alt="">
                                </div>
                            </div>
                        </div> 
                    </div>
                </div>
            </div>
            <div class="imWeb_main_center_footer">
                <div class="imWeb_main_center_footer_box">
                    <div class="upFile">
                        <input @change="getFile($event)" id="upload-input" type="file" multiple
                            accept="image/gif, image/jpg, image/png" />
                        <img id="imWeb_main_center_footer_upfile" src="/Public/images/imWebSendMessge.png" />
                    </div>
                    <textarea v-model="notedata" ref="textareaRef" @keydown="sendMessge('keydown')"
                        id="imWeb_main_center_footer_textarea"></textarea>
                    <div class="openMessge" @click="sendMessge('messge')">
                        <div class="configMessge">发送</div>
                    </div>
                </div>
            </div>
    
            <div class="showPopupImg" v-if="is_showPopupImg">
                <div class="showPopupImgMain" @click="closePopupImg">
                    <img ref="popupImg" :src="itemPopupImg" alt="">
                </div>
            </div>
        </div>
    </body>
    
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script type="text/javascript" src="/Public/Js/vue.min.js"></script>
    <script>
        const vm = new Vue({
            el: ".imWeb",
            data: {
                /*
                @params
                userInfo = { 
                uid,     用户uid
                path:    sanhuo or diamond   来自哪个页面  散货页面或者裸钻页面
                content: null 默认输入聊天框的内容
                client:  mobile or miniapp or pc  来自哪个页面
                }
                */
                userInfo: {$userinfo},
                wsUrl: "{$im_address}",
             
                isNextOpen: true, //判断是否已经打开了
                flag: true,//禁止多次点击
                kefuList: [], //与当前客服聊天的客户
                activeObj: {},//当前客服的信息
                notedata: "",//发送的聊天信息
                fileResult: '',//发送的图片
                timmer: '',//定时器ID
                closeTimmer: false,//是否关闭定时器
                nowMsg: [],//当前用户发送的信息
                storage_key: "",//当前客户的uid
                activePage: 1, //page 页数
                is_next: true,//用来判断是否可以继续上拉加载
                on_line: false,//是否在线
                is_showPopupImg: false, //用来显示全屏图片
                itemPopupImg: '', //点击显示的图片
                isShowPopUp: false,//用来显示右侧弹出层
                activeFy: "",//翻译
                timerId: '',//翻译定时器启动的ID
                clickTranslate: false,
                iframeData:{},//向嵌套进来的页面发送的信息对象
            },
    
            watch: {
                activeObj: function (newVal, oldVal) {
                    this.showLine(newVal)
                    this.getMessage(newVal, this.activePage)
                },
            },
            mounted() {
                var that = this
                var t = null
                this.$refs.chatPage_right_main_ref.addEventListener("scroll", function () {
                    if (t === null) {
                        t = setTimeout(() => {
                            if (that.$refs.chatPage_right_main_ref.scrollTop == 0 && that.is_next) {
                                that.is_next = false
                                that.activePage++
                                that.getMessage(that.activeObj, that.activePage)
                            }
                            t = null
                        }, 30)
                    }
                })
    
              
                window.addEventListener("message", function(event){
                    that.scrollToBottom()
                  var data = event.data;
                  console.log(data.params)
                  switch (data.cmd) {
                    case 'getFormJson': // 处理业务逻辑
                    if(that.userInfo.client == 'mobile' && data.params.content){ 
                        that.notedata = data.params.content
                     }
                        break;
                    }
                  });
            },
            created() {
                if(this.userInfo.content){ 
                    this.notedata = this.userInfo.content
                }
                var that = this
                this.storage_key = this.userInfo.path + '_' + this.userInfo.uid
                this.user_key = this.userInfo.path + "_" + this.userInfo.uid + '_' + this.userInfo.is_supply
                this.connectIm() //获取聊天响应数据
            },
            methods: {
                callBack(){ 
                    window.parent.postMessage({
                            cmd: 'callBack',
                            params:{
                            closeImWeb:true
                        }
                    }, '*');
                },
               
                clickImages(item) {
                    this.is_showPopupImg = !this.is_showPopupImg
                    this.itemPopupImg = item.content
                },
                closePopupImg() {
                    this.is_showPopupImg = false
                    this.itemPopupImg = ''
                },
                connectIm() {
                    var _this = this
                    if (this.closeTimmer && this.timmer) { //如果没有连接成功,或者断开连接,直接清除定时器
                        clearInterval(this.timmer);
                    }
                    this.webSocket = new WebSocket(this.wsUrl, [this.user_key])
                    this.webSocket.onopen = function (evt) { //1: 用来连接 websoket
                        console.log("Connection open ... binduser");
                    };
    
                    this.webSocket.onmessage = function (evt) { //2: 连接成功后台返回的响应
                        var data = JSON.parse(evt.data);
                        var type = data.type
                        if (type != 'pong') { //监听心跳,用来判断是否短路
                            _this.handleMsg(type, data.ret)
                        }
                    };
    
                    this.webSocket.onclose = function (evt) {
                        console.log("Connection closed. reconnect");
                    };
    
                    /*
                    状态1: 连接成功
                    状态3: 连接已关闭或者没有链接成功
                    */
    
                    this.timmer = setInterval(function () {
                        if (_this.webSocket.readyState == 1) {
                            data = { type: "ping" }
                            _this.webSocket.send(JSON.stringify(data))
                        }
                        if (_this.webSocket.readyState == 3) {
                            _this.closeTimmer = true
                            _this.connectIm()
                        }
                    }, 30000)
                },
                translateItem(item, index, to) {
                    var sendMsg = {
                        type: 'fanyi',
                        data: {
                            id: item.id,
                            to: to,
                            index: index
                        }
                    }
                    this.webSocket.send(JSON.stringify(sendMsg))
                },
                
                closeMainBox(){ 
                    if(!this.clickTranslate){ 
                        return
                    }
                    this.activeFy = ""
                    this.clickTranslate = false
                },
                // closeFy(item, index){ 
                //     // if (this.activeFy == '') {
                //     //     return
                //     // }
                //     // if (this.activeFy > 0 && this.activeFy != "") {
                //     //     // var tmp = JSON.parse(JSON.stringify(this.nowMsg[index]))
                //     //     // tmp.translation_content = ''
                //     // this.activeFy = ""
                //     //     this.clickTranslate = false
                //     //     // this.$set(this.nowMsg, index, tmp)
                //     // }
    
                // },
    
                translate(item, index) {  //点击翻译
                        this.activeFy = index
                        this.clickTranslate = true
                },
               
                handleMsg(type, ret) {
                    switch (type) {
                        case "fanyi":
                            var tmp = JSON.parse(JSON.stringify(this.nowMsg[ret.index]))
                            tmp.translation_content = ret.content
                            this.$set(this.nowMsg, ret.index, tmp)
                            break;
                        case "bindUser": //获取当前聊天人员信息
                            this.webSocket.send(JSON.stringify({ type: "getUserList", data: {} }))
                            break;
                        case 'getUserList'://获取当前人员聊天列表
                                var that = this
                                this.kefuList = ret.kefu
                                this.activeObj = ret.kefu[0] // 当前聊天客服
                                this.kefuList.forEach(function (item, index) {
                                    item.has_new_msg = false, //是否新信息
                                        item.is_chose = false, //当前是否点击
                                        item.type = 'im_kefu', //当前聊天人员类型
                                        item.content = ""//新信息
                                    if (that.activeObj.user_id == item.user_id) {
                                        that.kefuList[index].is_chose = true
                                    }
                                })
                            break;
                        case  "getMessage": //获取当前聊天人员信息
                            this.is_next = ret.msg.length > 0 ? true : false
                            if (ret.page == 1) {
                                this.nowMsg = ret.msg.reverse()
                                this.setScrollToBottomTime()
                            } else {
                                var tmp = ret.msg.reverse()
                                tmp = tmp.concat(this.nowMsg)
                                this.nowMsg = tmp
                                this.$nextTick(() => {
                                    var height = 0
                                    for (let index = 0; index < ret.msg.length; index++) {
                                        const element = this.$refs.chatPage_right_main_ref_for[index];
                                        height += element.clientHeight
                                    }
                                    this.$refs.chatPage_right_main_ref.scrollTop = height
                                })
                            }
    
                           
                            break;
                        case "recvMsg":
                            var that = this
                            var data = ret.msg
                            var menuImg = this.$refs.kehuMenuImg
                            this.kefuList.forEach((item, index) => {
                                if (item.supply_id == Number(data.to_uid)) {
                                    this.kefuList[index].has_new_msg = true
                                    this.kefuList[index].content = data.content
                                    that.isNextOpen = true
                                }
                            })
    
                            if (data.to_uid == this.activeObj.supply_id) {
                                this.nowMsg.push(data)
                            }
                            menuImg.setAttribute('src', that.isNextOpen ? '/Public/images/imWeb_ColorKehuMenu.png' : '/Public/images/imWeb_kehuMenu.png')
                                if(this.userInfo.client == "mobile"){ 
                                    var params  = ret.msg
                                        params.newMessge = true
                                        window.parent.postMessage({
                                            cmd: 'returnMessge',
                                            params:params
                                        }, '*');
                                }
                            this.setScrollToBottomTime()
                            break
                        case "showLine":
                            this.on_line = ret.is_online
                            break;
                    }
                },
                setScrollToBottomTime(){ 
                   new Promise((reslove)=>{ 
                      var id = setTimeout(()=>{ 
                          reslove(id)
                       },55)
                   }).then(id=>{
                       this.scrollToBottom()
                       clearTimeout(id)
                   })
                },
                 scrollToBottom (){
                       this.$nextTick(() => {  //思路 获取最外层包裹DIV,利用循环获取里面循环的每一个高度, 然后最外层整个盒子的高度等于循环div里面的总高度
                        var refDom = this.$refs.chatPage_right_main_ref_for //包裹数组循环的div
                        var refBox = this.$refs.chatPage_right_main_ref //包裹整个div的盒子
                        var len = 0
                        if (refDom && refDom.length > 0) {
                            refDom.forEach((item,index) => {
                                len += item.clientHeight
                            })
                            refBox.scrollTop = len
                        }
                    })
                },
                showLine: function (obj) {
                    obj.supply_id = obj.user_id
                    var sendMsg = {
                        type: 'showline',
                        data: obj
                    }
                    this.webSocket.send(JSON.stringify(sendMsg))
                },
                getMessage: function (to_obj, page) {
                    var sendMsg = {
                        type: 'getMessage',
                        msg_type: this.userInfo.path == 'sanhuo' ? 2 : 1,//散货2 钻石列表1
                        data: {
                            uid: this.userInfo.uid,
                            to_uid: to_obj.user_id,
                            to_type: 1,
                            page: page
                        },
                    }
                    this.webSocket.send(JSON.stringify(sendMsg))
                },
                getFile(event) {
                    var that = this
                    var form = new FormData();
                    let file = event.target.files[0];
                    form.append('file', file)
                    var fileUrl = this.userInfo.client == 'miniapp' ? '/Api_view/Com/uploadImg' : "/public/uploadImg"
                    axios.post(fileUrl, form).then(res => {
                        new Promise((reslove, resject) => {
                            if (res.data.status == 100) {
                                reslove(res.data.img_path)
                            } else {
                                resject(res)
                            }
                        }).then(res => {
                            this.fileResult = res
                            this.sendMessge('file', true)
                        })
                    })
                },
                sendMessge(str, type = '') {
                    if(str == 'keydown' && event.keyCode == 13 && this.notedata == ''){
                        event.preventDefault()
                        return
                    }
                   
                    if (str == 'messge' && this.notedata == '') {
                        return
                    }
    
                    if (event.keyCode && event.keyCode != 13) {
                        return
                    }
    
                    var params = {
                        content_type: 0,
                        content: type ? this.fileResult : this.notedata, //当前发送的信息
                        is_upload: type ? 1 : 0, // 1图片,0文本
                    }
                    /*
                     @params{ 
                         to_uid,        和谁聊天
                         type,          与当前聊天人的类型
                         msg,           当前是文本还是图片
                         content_type,  发送的内容
                     }
                    */
                    var sendMsg = {
                        type: "sendMsg",
                        data: { to_uid: this.activeObj.user_id, type: this.activeObj.type, msg: params.content, content_type: params.content_type, is_upload: params.is_upload }
                    };
    
                    var data = {
                        content: params.content,
                        add_time: this.dateFormat("YYYY-mm-dd HH:MM:SS", new Date()),
                        is_main: 1,
                        type: params.content_type,
                        is_upload: type ? 1 : 0 // 1图片,0文本
                    }
    
                    //发送的消息保存本地
                    if (this.nowMsg) {
                        this.nowMsg.push(data)
                    } else {
                        this.nowMsg = [data]
                    }
                    //发送消息
                    this.webSocket.send(JSON.stringify(sendMsg))
                    this.setScrollToBottomTime()
                    event.target.value = ''
                    this.notedata = ''
                    this.$refs.textareaRef.value = ''
                },
    
                clickehuList(item, index) {
                    for (let i in this.kefuList) {
                        if (Number(i) == index) {
                            if (this.kefuList[i].is_chose == true) {
                                this.kefuList[i].has_new_msg = false
                                this.clickKehu()
                                return
                            }
                            this.kefuList[i].is_chose = true
                            this.kefuList[i].has_new_msg = false
                            this.activePage = 1
                            this.activeObj = this.kefuList[i] // 当前聊天客服
                            this.clickKehu()
                            this.setScrollToBottomTime()
                        } else {
                            this.kefuList[i].is_chose = false
                        }
                    }
                },
                clickKehu() {
                    if (this.isNextOpen) {
                        this.isShowPopUp = true
                    }
                    var that = this
                    var imWebPopupRightList = ''
                    this.$nextTick(() => { imWebPopupRightList = this.$refs.imWeb_popup_right_list })
                    if (this.flag) {
                        var maxCount = 0
                        var timeId = setInterval(function () {
                            if (that.isNextOpen) {
                                that.flag = false
                                maxCount++
                                imWebPopupRightList.style.width = maxCount + '%'
                                if (maxCount == 75) {
                                    that.isNextOpen = !that.isNextOpen
                                    that.flag = !that.flag
                                    clearInterval(timeId)
                                    return
                                }
                            } else {
                                that.flag = false
                                maxCount = parseInt(imWebPopupRightList.style.width)
                                --maxCount
                                imWebPopupRightList.style.width = maxCount + '%'
                                if (maxCount == 0) {
                                    that.isNextOpen = true
                                    that.flag = true
                                    imWebPopupRightList.removeAttribute("class")
                                    that.isShowPopUp = false
                                    clearInterval(timeId)
                                    return
                                }
                            }
    
                        }, 5)
                    }
                },
    
                dateFormat(fmt, date) {
                    let ret;
                    const opt = {
                        "Y+": date.getFullYear().toString(),        // 年
                        "m+": (date.getMonth() + 1).toString(),     // 月
                        "d+": date.getDate().toString(),            // 日
                        "H+": date.getHours().toString(),           // 时
                        "M+": date.getMinutes().toString(),         // 分
                        "S+": date.getSeconds().toString()          // 秒
                        // 有其他格式化字符需求可以继续添加,必须转化成字符串
                    };
                    for (let k in opt) {
                        ret = new RegExp("(" + k + ")").exec(fmt);
                        if (ret) {
                            fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
                        };
                    };
                    return fmt;
                }
            },
        })
    </script>
    
    </html>
    
    

    相关文章

      网友评论

          本文标题:websoket

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