Events.php<?php use \GatewayWorker\Lib\Gateway; use \GatewayWorker\Lib\Db; if(!isset($_SESSION)){ session_start(); } /** &

Events.php

<?php
use \GatewayWorker\Lib\Gateway;
use \GatewayWorker\Lib\Db;
if(!isset($_SESSION)){
    session_start();
}
/**
 * 主逻辑
 * 主要是处理 onConnect onMessage onClose 三个方法
 * onConnect 和 onClose 如果不需要可以不用实现并删除
 */
class Events
{
    /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
    public static function onMessage($client_id, $data) {
        $message = json_decode($data, true);
        $message_type = strtolower($message['type']);
        switch($message_type) {
            case 'init':
                if(isset($message['id'])){
                    // 用户id 用户名 个性签名 头像等信息
                    $id        = $message['id'];
                    $username  = $message['username'];
                    $sign      = $message['sign'];
                    $avatar    = $message['avatar'];
                    // 将client_id与uid绑定,通过Gateway::sendToUid给这个uid发消息(在send_message.php中有调用)
                    $_SESSION['laychat']['id'] = $id;
                    Gateway::bindUid($client_id, $id);
                }
                // 通知当前客户端初始化
                $init_message = array(
                    'message_type' => 'init',
                    'client_id'    => $client_id,
                );
                $_SESSION['laychat']['client_id']  = $client_id;
                Gateway::sendToClient($client_id, json_encode($init_message));
                
                if(isset($message['id'])){
                    Gateway::updateSession($client_id, $message);
                    // 获取用户所在群组id
                    $db = Db::instance('laychat');
                    $group_id_array = $db->select('gid')->from('group_members')->where('uid=:uid')->bindValue('uid',$id)->column();
                    if($group_id_array){
                        foreach($group_id_array as $gid){
                            // 让当前客户端加入群组
                            Gateway::joinGroup($client_id, $gid);
                        }
                    }
                    // 通知所有客户端当前用户上线
                    $online_message = array(
                        'message_type' => 'online',
                        'id'           => $id
                    );
                    Gateway::sendToAll(json_encode($online_message));
                }
                return;
            case 'hide':
                $status_message = array(
                    'message_type' => $message_type,
                    'id'           => $message['uid'],
                );
                Gateway::sendToAll(json_encode($status_message));
                return;
            case 'online':
                $status_message = array(
                    'message_type' => $message_type,
                    'id'           => $message['uid'],
                );
                $_SESSION['online'] = $message_type;
                Gateway::sendToAll(json_encode($status_message));
                return;
            case 'ping':
                return;
            case 'logout':
                if(isset($message['id']) && !Gateway::isUidOnline($message['id'])){
                    $logout_message = array(
                        'message_type' => 'logout',
                        'id'           => $message['id']
                    );
                    Gateway::sendToAll(json_encode($logout_message));
                    Db::instance('laychat')->update('user')->cols(array('logout_timestamp'=>time(), 'status'=>'offline'))->where('uid = :uid')->bindValue('uid',$message['id'])->query();
                }
                return;
            case 'chatMessage':
                // 聊天数据
                $data = $message['data'];
                // 发送者,也就是当前登录用户的id
                $from = $data['mine']['id'];
                // 发送给谁
                $to   = $data['to']['id'];
                // 类型,私聊(friend)还是群组(group)
                $type = $data['to']['type'];
                // 消息格式
                $message_data = array(
                    'username' => $data['mine']['username'],
                    'avatar'   => $data['mine']['avatar'],
                    'id'       => $type === 'friend' ? $from : $to,
                    'type'     => $type,
                    'content'  => htmlspecialchars($data['mine']['content']),
                    'timestamp'=> time()*1000,
                    'from_id'  => $from,
                );
                $new_message = array(
                    'message_type' => 'chatMessage',
                    'data' => $message_data
                );
                // 根据类型走不同的接口发送
                switch($message['data']['to']['type']){
                    // 私聊
                    case 'friend':
                        Gateway::sendToUid($message['data']['to']['id'], json_encode($new_message));
                        break;
                    // 群聊
                    case 'group':
                        Gateway::sendToGroup($message['data']['to']['id'], json_encode($new_message), $client_id);
                        break;
                }
                //自己
                //Gateway::sendToCurrentClient(json_encode($new_message));
                //自己
                //Gateway::sendToClient($client_id, json_encode($new_message));
                //私聊
                //Gateway::sendToUid($message['data']['to']['id'], json_encode($new_message));
                //群聊
                //Gateway::sendToGroup($message['data']['to']['id'], json_encode($new_message), $client_id);
                //所有
                //Gateway::sendToAll(json_encode($new_message));
                return;
            default:
                echo "unknown message $data";
                //Gateway::sendToClient($client_id, $data);
        }
    }
    /**
    * 当用户断开连接时触发
    * @param int $client_id 连接id
    */
    public static function onClose() {
        // 有可能多页面登录,没有全部下线
        if(isset($_SESSION['laychat']['id']) && !Gateway::isUidOnline($_SESSION['laychat']['id'])){
            $logout_message = array(
                'message_type' => 'logout',
                'id'           => $_SESSION['laychat']['id']
            );
            Gateway::sendToAll(json_encode($logout_message));
            Db::instance('laychat')->update('user')->cols(array('logout_timestamp'=>time(), 'status'=>'offline'))->where('uid = :uid')->bindValue('uid',$_SESSION['laychat']['id'])->query();
        }
    }
}

start_businessworker.php

<?php 
use \Workerman\Worker;
use \GatewayWorker\BusinessWorker;

use \Workerman\Autoloader;

// 自动加载类
require_once __DIR__ . '/../vendor/autoload.php';

// bussinessWorker 进程
$worker = new BusinessWorker();
// worker名称
$worker->name = 'artimax_laychat';
// bussinessWorker进程数量
$worker->count = 4;
// 服务注册地址
$worker->registerAddress = __host__.':1238';

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START')) {
    Worker::runAll();
}

start_gateway.php

<?php 
use \Workerman\Worker;
use \GatewayWorker\Gateway;

// 自动加载类
require_once __DIR__ . '/../vendor/autoload.php';

// gateway 进程,这里使用Text协议,可以用telnet测试
$gateway = new Gateway("websocket://".__host__.":2346");
// gateway名称,status方便查看
$gateway->name = 'artimax_laychat';
// gateway进程数
$gateway->count = 1;
// 本机ip,分布式部署时使用内网ip
$gateway->lanIp = __host__;
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口 
$gateway->startPort = 2900;
// 服务注册地址
$gateway->registerAddress = __host__.':1238';

// 心跳间隔
$gateway->pingInterval = 12;
// 心跳数据
//$gateway->pingData = '{"message_type":"ping"}';

// 25秒内客户端不发来任何消息则认为客户端下线
$gateway->pingNotResponseLimit = 1;

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START')) {
    Worker::runAll();
}

start_register.php

<?php 
use \Workerman\Worker;
use \GatewayWorker\Register;

// 自动加载类
require_once __DIR__ . '/../vendor/autoload.php';

$register = new Register('text://'.__host__.':1238');

// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START')) {
    Worker::runAll();
}

javascript.js

/*
// +----------------------------------------------------------------------
// | Chat函数库
// +----------------------------------------------------------------------
// | Copyright (c) 2016-2017 http://www.nswlp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.nswlp.cn )
// +----------------------------------------------------------------------
// | Author: lwj <nswlp@nswlp.cn>
// +----------------------------------------------------------------------
*/
var WEB_SOCKET_SWF_LOCATION = SITE_URL + "/ymchat/static/swf/WebSocketMain.swf";
var WEB_SOCKET_DEBUG = true;
var WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
var imgerror = SITE_URL + '/ymchat/static/imgs/onerror.jpg';
var requrl   = SITE_URL + '/ymchat.php?app=ymchat/';
var laychat  = {
    appName           : 'YaMeichat',
    initUrl           : requrl + 'default&act=init',
    sendMessageUrl    : requrl + 'default&act=sendmessage',
    membersUrl        : requrl + 'haystack&act=members&',
    uploadImageUrl    : requrl + 'haystack&act=uploadimg&',
    uploadFileUrl     : requrl + 'haystack&act=uploadfile&',
    chatLogUrl        : requrl + 'haystack&act=chatlog&',
    bindUrl           : requrl + 'default&act=bind',
    updateSignUrl     : requrl + 'haystack&act=updatesign&',
    msgBoxUrl         : requrl + 'haystack&act=msgbox&',
    sysmsgbox         : requrl,
    agreeUrl          : requrl + 'haystack&act=agree&',
    getNoticeUrl      : requrl + 'haystack&act=getnotice&',
    ligature          : requrl + 'default&act=connected',
    address           : (_con.is_ssl ? 'wss://' : 'ws://') + (_con.__host__ || document.domain) +':' + _con._wsport_,
    isMobile          : false,
    setMin            : true,
    enableAudio       : false,
    enableVideo       : false,
    enableGroup       : false,
    enableFriend      : false,
    initSkins         : '24.jpg',
    voice             : 'default.mp3',
    findUrl           : false,
    inited            : 0,
    socket            : null,
    jq                : null,
    /*系统分组tab*/
    issystemtab       : true,
    /*开启在线状态*/
    islinestate       : false,
    /*开启签名*/
    issign            : false,
    /*开启关于*/
    copyright         : true,
    /*开启皮肤*/
    skins             : false,
    /*开启底部消息中心*/
    sysmsg            : true,
    /*开启搜索*/
    searchs           : false,
    /*客服是否可查看聊天记录*/
    brief             : false,
    notice            : _con.notice, //       是否开启桌面消息提醒,默认false
    //skin            : ['aaa.jpg'], //新增皮肤
    //right           : '5px', //      主面板相对浏览器右侧距离
    //minRight        : '5px', //      聊天面板最小化时相对浏览器右侧距离
    /*特效*/
    effects           : false,
    /*自动匹配回复*/
    automatching      : true,
    /*end*/
    open              : function() {
        if (this.inited) return;
        if(this.isIE6or7()) return;
        if(!this.jq) this.jq = $;
        this.connectWorkerman();
        this.inited = 1;
    },
    isIE6or7 : function(){
        var b = document.createElement('b');
        b.innerHTML = '<!--[if IE 5]><i></i><![endif]--><!--[if IE 6]><i></i><![endif]--><!--[if IE 7]><i></i><![endif]-->';
        return b.getElementsByTagName('i').length === 1;
    },
    connectWorkerman : function() {
        laychat.socket        = new WebSocket(laychat.address);
        laychat.socket.onopen = function(){
            var login_data = '{"type":"init","id":"'+ _con.uinfo.id + '","username":"'+ _con.uinfo.username + '","avatar":"'+ _con.uinfo.avatar + '","sign":"'+ _con.uinfo.sign + '"}';
            //laychat.socket.send(JSON.stringify({type: 'init',id:_con.uinfo.id}));
            laychat.socket.send(login_data);
        };

        laychat.socket.onmessage = function(e){
            var msg = JSON.parse(e.data);
            // 如果layim还没有初始化就收到消息则忽略(init消息除外)
            if(!msg.message_type || (msg.message_type != 'init' && !layui.layim)) return;
            switch(msg.message_type) {
                // 初始化im
                case 'init':
                    /*ajax请求,绑定client_id和uid*/
                    $.ajax({
                        url: laychat.bindUrl,
                        type: 'post',
                        data: {client_id: msg.client_id},
                        dataType: 'json',
                        success: function(bindJson){
                            if(bindJson.code == 0){
                                $.ajax({
                                    url: laychat.initUrl,
                                    type: 'post',
                                    data: {},
                                    dataType: 'json',
                                    success: function(initData){
                                        if(initData.code != 0){
                                            console.log('初始化数据失败:' + initData.msg);
                                        }else{
                                            laychat.initIM(bindJson, initData.data);
                                        }
                                    },
                                    error: function(xhr, ajaxOptions, thrownError){
                                        console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                                    }
                                });
                            }else{
                                console.log('绑定客户端失败:' + bindJson.msg);
                            }
                        },
                        error: function(xhr, ajaxOptions, thrownError){
                            console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                        }
                    });
                    return;
                // 添加一个用户到好友列表
                case 'addList':
                    if($('#layim-friend'+msg.data.id).length == 0 && layui.layim.cache() && layui.layim.cache().id != msg.data.id){
                        return layui.layim.addList && layui.layim.addList(msg.data);
                    }
                    if (msg.data.type == 'friend') {
                        layui.layim.setFriendStatus && layui.layim.setFriendStatus(msg.data.id, 'online');
                    }
                    return;
                // 收到一个消息
                case 'chatMessage':
                    msg.data.content = String(msg.data.content);
                    if(msg.data.type == 'group') {
                        if(msg.data.from_id != layui.layim.cache().mine.id){
                            layui.layim.getMessage(msg.data);
                        }
                    }else if(layui.layim.cache().mine.id != msg.data.id){
                        layui.layim.getMessage(msg.data);
                    }
                    if(laychat.effects){
                        autoword.getword(msg.data.content);
                    }
                    lastspeech(msg.data.content,msg.data.from_id);
                    
                    if(msg.data.type == 'kefu'){
                        /*重置超时 - 按正常道理接收不应该触发重置超时*-/
                        time_out();
                        /*重置超时自动断开*/
                        break_out();
                        layui.layim.setChatStatus('');
                    }
                    return;
                case 'msgbox':
                    layui.layim.msgbox && layui.layim.msgbox(msg.count);
                    return;
                case 'oppo':
                    layui.layim.setChatStatus(msg.msg_data);
                    layui.layim.setFriendStatus && layui.layim.setFriendStatus(msg.id, msg.status);
                    return;
                // 退出
                case 'logout':
                    //layui.layim.setChatStatus('<span style="color:#FF5722;">对方不在线</span>');
                    return layui.layim.setFriendStatus && layui.layim.setFriendStatus(msg.id, 'offline');
                // 隐身
                case 'hide':
                    //layui.layim.setChatStatus('<span style="color:#FF5722;">对方不在线</span>');
                    return layui.layim.setFriendStatus && layui.layim.setFriendStatus(msg.id, 'offline');
                // 上线
                case 'online':
                    //layui.layim.setChatStatus('<span>在线</span>');
                    return layui.layim.setFriendStatus && layui.layim.setFriendStatus(msg.id, 'online');
                // 人工客服
                case 'ligature':
                    if(_con.ligature){
                        $.ajax({
                            url: laychat.ligature,
                            type: 'post',
                            data: {data:{kefu:_con.ligature,laun:msg.data,to:_con.uinfo}},
                            dataType: 'json',
                            success: function(lgt){},
                            error: function(xhr, ajaxOptions, thrownError){
                                console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                            }
                        });
                    }else{
                        /*接收客服信息*/
                        _con.ligature = msg.data;
                        /*给客服提示已接上*/
                        var kdata = {system:true,mine:_con.uinfo,to:_con.ligature};
                        kdata.mine.content = sprintf(_con.d_replay.userhrough,_con.uinfo.username);
                        kdata.mine.mine    = true;
                        kdata.to.type      = 'service';
                        $.post(laychat.sendMessageUrl, {data: kdata}, function(data){
                            if(data.code != 0) {
                                ymservice.getms(_con.d_replay.userfailure);
                                _con.ligature = null;
                            }else{
                                /*提示已接上*/
                                ymservice.getms(sprintf(_con.d_replay.yetthrough,_con.ligature.username),true);
                                /*开始超时自动断开*/
                                if(_con.d_replay.break_out) break_out();
                                /*接上客服就不要默认的超时了*/
                                keeptimes({
                                    key   : 'time_out',
                                    num   : 0,
                                    bac   : null,
                                    feed  : null,
                                    clear : true
                                });
                                /*end*/
                            }
                        }, 'json');
                    }
                    return;
                // 订单消息
                case 'ordermsg':
                    // 自动弹出
                    $('[type-id="sysmsgbox"]').click();
                    return;
                // 物流消息
                case 'logistics':
                    // 自动弹出
                    $('[type-id="logistics"]').click();
                    return;
                // 系统消息
                case 'systemmsg':
                    // 自动弹出
                    $('[type-id="systemmsg"]').click();
                    return;
                // 全部消息
                case 'allmsg':
                    // 自动弹出
                    $('[type-id="systemmsg"]').click();
                    return;
                case 'beiyong':
                    
                    return;
            }
        }
        laychat.socket.onclose = laychat.connectWorkerman;
    },
    sendHeartbeat : function() {
        if(this.socket && this.socket.readyState == 1) {
            this.socket.send(JSON.stringify({type :'ping'}));
        }
    },
    /*关闭事件*/
    unload : function(){
        if(this.socket){
            this.socket.send(JSON.stringify({type :'logout',id:_con.uinfo.id}));
            //layui.layer.msg(_con.uinfo.username + ' 下线了', {time: 7000});
        }
    },
    initIM : function(msg_data, init_data){
        var unread_msg_tips = function(msg_data){
            // 离线交易消息
            if(msg_data.msgcentre){
                var clicks = false;
                $.each(msg_data.msgcentre,function(i,v){
                    if(parseInt(v)){
                        if(i == 'systemmsg') layui.layim.msgbox('new');
                        else $('[type-id="+i+"]').addClass('msgnotify');
                        clicks = true;
                    }
                });
                if(clicks) $('.layui-layim-min').click();
            }
            // 离线消息
            for(var key in msg_data.unread_message){
                layui.layim.getMessage(JSON.parse(msg_data.unread_message[key]));
            }
            if (msg_data.unread_notice_count) {
                // 设置消息盒子未读计数
                layui.layim.msgbox && layui.layim.msgbox(msg_data.unread_notice_count);
            }
            return;
        };
        // layim已经初始化了,则只提示未读消息
        if(this.inited == 2) {
            return unread_msg_tips(msg_data);
        }
        this.inited = 2;
        // 心跳数据,用来保持长链接,避免socket链接长时间不通讯被路由节点防火墙关闭
        setInterval('laychat.sendHeartbeat()', 12000);

        var module = laychat.isMobile ? ['mobile','layedit'] : ['layim','layedit'];
        layui.use(module, function(layim){
            _con.layedit_s = layui.layedit;
            _con.ymlayim   = layim;
            _con.ymmsg     = layui.layer;
            if (laychat.isMobile) {
                var mobile = layui.mobile
                    , layim = mobile.layim
                    , layer = mobile.layer;
                layui.layim = layim;
                layui.layer = layer;
            }
            //layim建立就绪
            layim.on('ready', function(res){
                // 离线消息
                return unread_msg_tips(msg_data);
            });
            //监听发送消息
            layim.on('sendMessage', function(data){
                var sendata = data;
                if(_con.ligature){
                    var kdata = {mine:_con.uinfo,to:_con.ligature};
                    kdata.mine.content = data.mine.content;
                    kdata.mine.mine    = true;
                    kdata.to.type      = 'service';
                    sendata = kdata;
                }
                $.ajax({
                    url: laychat.sendMessageUrl,
                    type: 'post',
                    data: {data: sendata},
                    dataType: 'json',
                    success: function(sendData){
                        if(sendData.code != 0){
                            layui.layer.msg(sendData.msg, {time: 7000});
                        }
                    },
                    error: function(xhr, ajaxOptions, thrownError){
                        console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                    }
                });
                if(laychat.effects){
                    autoword.sendword(data.mine.content);
                }
                lastspeech(data.mine.content,data.to.id);
                if(data.to.type == 'kefu'){
                    /*重置超时*/
                    time_out();
                    /*重置超时自动断开*/
                    break_out();
                    if(!_con.ligature){
                        layim.setChatStatus('<span style="color:#FF5722;">对方正在输入......</span>');
                    }
                }
            });
            //监听在线状态的切换事件
            layim.on('online', function(data){
                laychat.socket.send(JSON.stringify({type: data,uid:layui.layim.cache().mine.id}));
            });
            //更改个性签名
            layim.on('sign', function(value){
                $.post(laychat.updateSignUrl, {sign: value} , function(data){
                    if(data.code != 0) {
                        layui.layer.msg(data.msg, {time: 7000});
                    }
                }, 'json');
            });
            //监听自定义工具栏点击,以添加代码为例
            layim.on('tool(code)', function(insert){
                layui.layer.prompt({
                        title: '插入代码 - 工具栏扩展示例'
                        ,formType: 2
                        ,shade: 0
                    },
                    function(text, index){
                        layui.layer.close(index);
                        insert('[pre class=layui-code]' + text + '[/pre]'); //将内容插入到编辑器
                });
            });
            layim.on('close', function(value){
                alert(999999);
            });
            //富文本
            //layedit.build('ftextarea');
            
            layui.layim.config({
                //初始化接口
                init: init_data
                //查看群员接口
                ,members: {
                    url: laychat.membersUrl
                }
                // 上传图片
                ,uploadImage: {
                    url: laychat.uploadImageUrl
                }
                // 上传文件
                ,uploadFile: {
                    url: laychat.uploadFileUrl
                }

                //扩展工具栏
                /*,tool: [
                    {
                        alias : 'code'
                        ,title: '代码'
                        ,icon : '&#xe64e;'
                    }
                ]*/
                ,initSkin: laychat.initSkins
                ,isgroup: laychat.enableGroup
                ,isfriend: laychat.enableFriend
                ,msgbox: laychat.msgBoxUrl ? laychat.msgBoxUrl+(laychat.msgBoxUrl.indexOf('?') == -1 ? '?' : '&')+'getNoticeUrl='+encodeURI(laychat.getNoticeUrl)+'&agreeUrl='+encodeURI(laychat.agreeUrl) : false
                //聊天记录地址
                ,chatLog: laychat.chatLogUrl
                ,find: laychat.findUrl
                ,issigns: laychat.issign
                ,copyright: laychat.copyright
                ,skins: laychat.skins
                ,sysmsg: laychat.sysmsg
                ,sysmsgbox: laychat.sysmsgbox
                ,issystemtab: laychat.issystemtab
                ,islinestate: laychat.islinestate
                ,title: _con.uinfo.username ? _con.uinfo.username : laychat.appName
                ,min: laychat.setMin
                ,searchs: laychat.searchs
                ,isAudio: laychat.enableAudio
                ,isVideo: laychat.enableVideo
                ,voice: laychat.voice
                ,_brief_: laychat.brief
            });

        });
    }
};
if(_con.ymopen) laychat.open();

上一篇:workerman简单例子

下一篇:在linux服务器上装svn版本管理,本地代码自动部署到项目

评论列表
发表评论
称呼
邮箱
网址
验证码(*)
热评文章
相关阅读