美文网首页
网易云信IM(H5移动端SDK)使用

网易云信IM(H5移动端SDK)使用

作者: il_xin | 来源:发表于2018-12-29 09:00 被阅读0次
    QQ截图20181229085012.png

    最近体验了下云信SDK
    直接上干货,不废话!

    下载地址:
    SDK:https://netease.im/im-sdk-demo
    Demo:https://github.com/netease-im/NIM_Web_Demo_H5
    入手指南:https://dwz.cn/Hq6Biq2O
    服务端Api:https://dwz.cn/F3Xpc1aR
    私聊上传:http://nos.netease.com/vod163/upload.js
    表情:http://www.jq22.com/jquery-info16078

    本篇内容为:云信Sdk+jquery.emoticons实现聊天功能
    应用在web移动端,用户间会话沟通和客服等功能。
    PS:本篇提供基础实现方法,不提供界面ui,用哪个表情插件都可以,比如大笑的表情对应[大笑],转义后从json找到对应url。

    一.获取自己的appKey,具体方法云信官方有。

    注册云信帐号——>登录网易云信管理后台——>创建应用——>获取appkey

    二.引入SDK,demo分离太麻烦,此处并未使用

    <script type="text/javascript" src="/js/im/NIM_Web_SDK_v5.9.1.js"></script>
    需要注意的是:在本机静态页面测试时容易报错,需要发布项目,使用127.0.0.1:XX或者localhost等都可以过关;在使用fis3等优化时,如果进入页面sdk报错,将sdk单独处理不要fis等。

    三.初始化参数

    会话列表页常用:

    var nim = SDK.NIM.getInstance({
        // 初始化SDK
        appKey: 'xxx',
        account: 'xxx',
        token: 'xxx',
        customTag: 'tag',
        onconnect: onConnect,
        onerror: onError,
        onwillreconnect: onWillReconnect,
        ondisconnect: onDisconnect,
        // 多端
        onloginportschange: onLoginPortsChange,
        // 会话
        onsessions: onSessions,
        onupdatesession: onUpdateSession,
        // 同步完成
        onsyncdone: onSyncDone
    });
    
    //此处隐藏onConnect,onError等方法
    //请复制官方初始化代码,然后修改加入以下
    
    function onSessions(sessions) {
        console.log('收到会话列表', sessions);
        data.sessions = nim.mergeSessions(data.sessions, sessions);
        updateSessionsUI(sessions);
    }
    
    function onUpdateSession(session) {
        console.log('会话更新了', session);
        data.sessions = nim.mergeSessions(data.sessions, session);
        //对html进行局部更新,和grid操作类似
        updatePartUI(session);
    }
    

    四.会话列表展现

    function updateSessionsUI(sessions){
        //这里取当天时间,后面会用在列表会话时间上,例如:12-20(今日之前)和9:35(当日)
        var today = new Date(new Date().setHours(0, 0, 0, 0)) / 1;
        //...你的时间处理,可使用下方的timestampToTime()
        //你的页面更新操作
        var html = ""
        for (var i = 0 ; i < sessions.length; i++) {
            //...
            html+="...";
        }
        $('#').append(html);
    }
    
    function updatePartUI(session){
        //根据列表html结构更新和排序
    }
    
    //时间戳处理
    function timestampToTime(timestamp) {
        var times = new Date(parseInt(timestamp));
        var t = times.toLocaleDateString().replace(/\//g, "-").substr(5,9)+ " " + times.toTimeString().substr(0,5);     
        return t;
    }
    
    //私聊
    $(document).on("click",'#nim_container table',function(){
        //需要提供account和token来进行双方会话
        //在sessions会话列表里都是有的
        var im_account ="";
        var im_token = "";
        var url="../index?account_id="+im_account+"&token_id="+im_token;
        window.location.href=url; 
    });
    

    五.私聊、表情、图片上传的实现

    //加载云信SDK
    //获取会话对象
    var nimParam = getUrlParam();
    var data = {};
    var nim = SDK.NIM.getInstance({
        // 初始化SDK
        appKey: 'xxxxxx',
        account: nimParam.account_id,
        token: nimParam.token_id,
        customTag: 'tag',
        onconnect: onConnect,
        onerror: onError,
        onwillreconnect: onWillReconnect,
        ondisconnect: onDisconnect,
        // 多端
        onloginportschange: onLoginPortsChange,
        // 消息
        onmsg: onMsg,
        // 同步完成
        onsyncdone: onSyncDone
    });
    
    //...没什么用的我就不写了,自己加自己要的
    
    function onMsg(msg) {
        console.log('收到消息', msg.scene, msg.type, msg);
        pushMsg(msg);
    }
    
    //同步完成后获取历史信息
    function onSyncDone() {
        nim.getHistoryMsgs({
          scene: 'p2p',
          to: nimParam.nim_fromId,
          done: getHistoryMsgsDone
      });
    }
    
    function getHistoryMsgsDone(error, obj) {
        if (!error) {
            console.log(obj.msgs);
            pushMsg(obj.msgs);
        }
    }
    
    //输出聊天信息,表情转义
    function pushMsg(msgs) {
        if (!Array.isArray(msgs)) { msgs = [msgs]; }
        if (msgs[0]!=null) {
            var sessionId = msgs[0].sessionId;
            data.msgs = data.msgs || {};
            data.msgs[sessionId] = nim.mergeMsgs(data.msgs[sessionId], msgs);
            var emoticonPath = '/img/im/';
            var msgHtml , title , emoticonUrl , shwoType ,msgsText;
            var filter = /[\[\]]/g;
            for (var i = msgs.length - 1; i >= 0; i--) {
                //输出内容
                if (msgs[i].type=="text"){
                    msgsText = msgs[i].text;
                    //表情字符转义
                    var msgsList = msgsText.match(/\[[\u4e00-\u9fa5]*\w*\]/g);
                    if(msgsList){
                       for(var e=0;e<msgsList.length;e++){
                            title = msgsList[e].replace(filter,'');
                            //获取表情路径
                            for (var p = 0; p < emoticonsList.length; p++) {
                                if (emoticonsList[p].title==title) {
                                    emoticonUrl = emoticonsList[p].url;
                                    break;
                                }
                            }
                            //错误格式默认表情笑容
                            if (emoticonUrl == undefined) {
                                emoticonUrl = emoticonsList[0].url;
                            }
                            msgsText = msgsText.replace(msgsList[e],'<img src="'+emoticonPath+"emoticons/"+emoticonUrl+'"/> ');
                        }    
                    }
                }else if (msgs[i].type=="image"){
                    msgsText = '<img src="'+msgs[i].file.url+'"/>';
                }
    
                //以下是你的html结构
                //你的对话框样式
                if (msgs[i].flow=="out") {
                    shwoType = "";  
                }else{
                    //..
                }
                msgHtml="<div class='"+shwoType+"'><div class='msg'><div class='portrait'>"
                    +"<img src='"+emoticonPath+"touxiang.png' alt=''/></div>"
                    +"<div class='msg_content'>"+msgsText+"</div></div></div>";
                upView(msgHtml);
            }
            anchor();
        }
    }
    
    //发送信息成功后更新
    function sendMsgDone(error, msg) {
        console.log('发送' + msg.scene + ' ' + msg.type + '消息' + (!error?'成功':'失败') + ', id=' + msg.idClient);
        pushMsg(msg);
    }
    
    //回车和发送按钮操作
    $('#dialogue').bind('keypress', function (event) { 
        if (event.keyCode == "13") { 
            sendMsgs();
        }
    });
    
    $('.im_send').click(function(){
        sendMsgs();
    });
    
    //发送文本信息
    function sendMsgs(){
        var dialogue = document.getElementById("dialogue");
        if($.trim(dialogue.value).length != 0){
            var msg = nim.sendText({
                scene: 'p2p',
                to: nimParam.nim_fromId,
                text: dialogue.value,
                done: sendMsgDone
            });
            dialogue.value = "";
        }
    }
    
    //发送图片,具体参数请查看官方API
    //此处需要upload.js、md5.js(页首有下载链接)
    function sendFile(curFile){
        nim.sendFile({
            scene: 'p2p',
            to: nimParam.nim_fromId,
            type: 'image',
            fileInput: curFile,
            fastPass: '{"w":200,"h":110,"md5":"xxxxxxxxx"}',
            beginupload: function(upload) {
                // - 如果开发者传入 fileInput, 在此回调之前不能修改 fileInput
                // - 在此回调之后可以取消图片上传, 此回调会接收一个参数 `upload`, 调用 `upload.abort();` 来取消文件上传
            },
            uploadprogress: function(obj) {
                // console.log('文件总大小: ' + obj.total + 'bytes');
                // console.log('已经上传的大小: ' + obj.loaded + 'bytes');
                // console.log('上传进度: ' + obj.percentage);
                // console.log('上传进度文本: ' + obj.percentageText);
            },
            uploaddone: function(error, file) {
                // console.log(error);
                // console.log(file);
                console.log('上传' + (!error?'成功':'失败'));
            },
            beforesend: function(msg) {
                // console.log('正在发送p2p image消息, id=' + msg.idClient);
            },
            done: sendMsgDone
        });
    }
    
    /*更新视图*/
    function upView(html){
        $('#js-nim_msg').append(html);
    }
    
    //页末锚点
    function anchor(){
        $('body,html').animate({scrollTop: $('.msg_content:last').offset().top});
    }
    
    //获取nim_url参数
    function getUrlParam(name) {
        var search=location.search;
        var params={}; 
        if(search!=""){
            search.slice(1).split("&").forEach(function(val){
                var arr=val.split("=");
                params[arr[0]]=arr[1]; 
            });
        }
        return params;   //返回params
    }
    
    //表情页展现
    $('.nim_expression').click(function(){
        resetmode();
        if($('#js-nim_emoticon').is(':hidden')){
            $('#js-nim_emoticon').show(200);
            $('#js-nim_footer').css('bottom','2.2rem');
            $('#nim_anchor').height('2.2rem');
        }
        anchor();
    });
    
    //添加文件
    $('#nim_more').click(function(){
        //fileInput为type='file'的文本框,点击按钮图片时单击文本框,上传的文件必须储存在file内。
        $("#fileInput").click();
    });
    
    //重置表情、更多内容等都写在这个位置
    function resetmode(){
        $('#js-nim_more').hide(200);
        $('#js-nim_emoticon').hide(200);
        $('#nim_anchor').height(0);
        $('#js-nim_footer').css('bottom','0rem');
    }
    
    //载入表情
    $.emoticons({
        'activeCls':'trigger-active'
    });
    
    //选择表情后转义添加到文本
    $('#im_emoticons img').click(function(){
        var format = "["+$(this).attr("title")+"]";
        var dialogue = document.getElementById("dialogue");
        dialogue.value = dialogue.value + format;
    });
    
    
    /**
     *  加载表情,位置自己放
     */
    ;(function (factory) {
        if (typeof define === "function" && (define.amd || define.cmd) && !jQuery) {
            // AMD或CMD
            define([ "jquery" ],factory);
        } else if (typeof module === 'object' && module.exports) {
            // Node/CommonJS
            module.exports = function( root, jQuery ) {
                if ( jQuery === undefined ) {
                    if ( typeof window !== 'undefined' ) {
                        jQuery = require('jquery');
                    } else {
                        jQuery = require('jquery')(root);
                    }
                }
                factory(jQuery);
                return jQuery;
            };
        } else {
            //Browser globals
            factory(jQuery);
        }
    }(function ($) {
        $.emoticons = function(parameter,getApi) {
            if(typeof parameter == 'function'){ //重载
                getApi = parameter;
                parameter = {};
            }else{
                parameter = parameter || {};
                getApi = getApi||function(){};
            }
            var defaults = {
                'prefix':'widget',
                'publisherCls':'publisher',
                'triggerCls':'trigger',
                'activeCls':'active',
                'path':'/img/im/emoticons/',
                'list':emoticonsList,
                'top':0,
                'left':0
            };
            var options = $.extend({}, defaults, parameter);
            var _api = {};
            var $document = $(document);
            var $emoticon = $('#im_emoticons');
            var _hash = {};
            $.each(options.list,function(index,item){
                _hash[item.title] = options.path+item.url;
                $emoticon.append('<img title="'+item.title+'" src="'+_hash[item.title]+'"/>');
            });
            //初始化
            getApi(_api);
            return this;
        };
    }));
    
    var emoticonsList = [{title:'微笑',url:'weixiao.gif'},{title:'嘻嘻',url:'xixi.gif'},{title:'哈哈',url:'haha.gif'},{title:'可爱',url:'keai.gif'},{title:'可怜',url:'kelian.gif'},{title:'挖鼻',url:'wabi.gif'},{title:'吃惊',url:'chijing.gif'},{title:'害羞',url:'haixiu.gif'},{title:'挤眼',url:'jiyan.gif'},{title:'闭嘴',url:'bizui.gif'},{title:'鄙视',url:'bishi.gif'},{title:'爱你',url:'aini.gif'},{title:'泪',url:'lei.gif'},{title:'偷笑',url:'touxiao.gif'},{title:'亲亲',url:'qinqin.gif'},{title:'生病',url:'shengbing.gif'},{title:'太开心',url:'taikaixin.gif'},{title:'白眼',url:'baiyan.gif'},{title:'右哼哼',url:'youhengheng.gif'},{title:'左哼哼',url:'zuohengheng.gif'},{title:'嘘',url:'xu.gif'},{title:'衰',url:'shuai.gif'},{title:'吐',url:'tu.gif'},{title:'哈欠',url:'haqian.gif'},{title:'抱抱',url:'baobao.gif'},{title:'怒',url:'nu.gif'},{title:'疑问',url:'yiwen.gif'},{title:'馋嘴',url:'chanzui.gif'},{title:'拜拜',url:'baibai.gif'},{title:'思考',url:'sikao.gif'},{title:'汗',url:'han.gif'},{title:'困',url:'kun.gif'},{title:'睡',url:'shui.gif'},{title:'钱',url:'qian.gif'},{title:'失望',url:'shiwang.gif'},{title:'酷',url:'ku.gif'},{title:'色',url:'se.gif'},{title:'哼',url:'heng.gif'},{title:'鼓掌',url:'guzhang.gif'},{title:'晕',url:'yun.gif'},{title:'悲伤',url:'beishang.gif'},{title:'抓狂',url:'zhuakuang.gif'},{title:'黑线',url:'heixian.gif'},{title:'阴险',url:'yinxian.gif'},{title:'怒骂',url:'numa.gif'},{title:'互粉',url:'hufen.gif'},{title:'书呆子',url:'shudaizi.gif'},{title:'愤怒',url:'fennu.gif'},{title:'感冒',url:'ganmao.gif'},{title:'心',url:'xin.gif'},{title:'伤心',url:'shangxin.gif'},{title:'猪',url:'zhu.gif'},{title:'熊猫',url:'xiongmao.gif'},{title:'兔子',url:'tuzi.gif'},{title:'OK',url:'ok.gif'},{title:'耶',url:'ye.gif'},{title:'GOOD',url:'good.gif'},{title:'NO',url:'no.gif'},{title:'赞',url:'zan.gif'},{title:'来',url:'lai.gif'},{title:'弱',url:'ruo.gif'},{title:'草泥马',url:'caonima.gif'},{title:'神马',url:'shenma.gif'},{title:'囧',url:'jiong.gif'},{title:'浮云',url:'fuyun.gif'},{title:'给力',url:'geili.gif'},{title:'围观',url:'weiguan.gif'},{title:'威武',url:'weiwu.gif'},{title:'话筒',url:'huatong.gif'},{title:'蜡烛',url:'lazhu.gif'},{title:'蛋糕',url:'dangao.gif'},{title:'发红包',url:'fahongbao.gif'}];
    

    六.备注

    upload.js需要使用自己的AppKey
    fileExts: ['JPG','PNG','JPGE','GIF']
    ...后续再加,今天先到这里

    相关文章

      网友评论

          本文标题:网易云信IM(H5移动端SDK)使用

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