websoket

2021-09-02  本文已影响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>

上一篇下一篇

猜你喜欢

热点阅读