heijinli

挥手,握手就不解释了。直接上代码

启动swoft ws的服务

 

 

<?php declare(strict_types=1);
/**
 * This file is part of Swoft.
 *
 * @link     https://swoft.org
 * @document https://swoft.org/docs
 * @contact  group@swoft.org
 * @license  https://github.com/swoft-cloud/swoft/blob/master/LICENSE
 */

namespace App\WebSocket;

use Swoft\Http\Message\Request;
use Swoft\Session\Session;
use Swoft\Http\Message\Response;
use Swoft\WebSocket\Server\Annotation\Mapping\OnClose;
use Swoft\WebSocket\Server\Annotation\Mapping\OnMessage;
use Swoft\WebSocket\Server\Annotation\Mapping\OnHandshake;
use Swoft\WebSocket\Server\Annotation\Mapping\OnOpen;
use Swoft\WebSocket\Server\Annotation\Mapping\WsModule;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use function server;

use Swoft\Redis\Exception\RedisException;
use Swoft\Redis\Pool;
use Swoft\Redis\Redis;
use Swoft\Log\Helper\CLog;
use Swoft\Db\DB;
use Swoft\Task\Task;


/**
 * Class EchoModule
 *
 * @WsModule("echo")
 */
class EchoModule
{
    /**
     * @OnOpen()
     * @param Request $request
     * @param int     $fd
     */
    public function onOpen(Request $request, int $fd): void
    {
        Session::current()->push("Opened, welcome #{$fd}!");
    }

    /**
     * @OnMessage()
     * @param Server $server
     * @param Frame  $frame
     * blacklist 黑名单
     * Blockkeywords 屏蔽关键字
     * 检测客服是否在线
     * 判断条件,搜索关键字。匹配自动回复内容
     */
    public function onMessage(Server $server, Frame $frame): void
    {
        CLog::info(\'talk: %s \', $frame->data);

        $data = json_decode($frame->data, true);

        if ($data[\'flag\'] == \'init\') {
            $res = Redis::set(\'user_fd\'.$data[\'from\'], $frame->fd);
        }

        $blacklist = Redis::get(\'blacklist\');

            if (empty($blacklist)) {

                $list = Db::table(\'db_customer_blacklist\')->where(\'status\',1)->select(\'user_id\')->get();

                $blacklist = [];

                foreach ($list as $k => $v) {
                    $blacklist[] = $v[\'user_id\'];
                }

            }

            $blackStr = implode(",", $blacklist);

            if(strpos($blackStr, $data[\'from\']) !== false){
                $server->push($frame->fd, json_encode([\'content\'=>\'卧槽~!被禁言了\',\'from\'=>$data[\'to\']]));die;
            }

        $BlockkeywordsStr = Redis::get(\'Blockkeywords\');

            if (empty($Blockkeywords)) {
                $Blocklist = Db::table(\'db_customer_blockkeyword\')->where(\'status\',1)->select(\'keywords\')->get();

                $BlockkeywordsStr = \'\';

                foreach ($Blocklist as $k1 => $vo) {
                    if ($k1 == 0) {
                        $BlockkeywordsStr .= $vo[\'keywords\'];
                    }else{
                        $BlockkeywordsStr .= \',\'.$vo[\'keywords\'];
                    } 
                }

            }

            $BlockkeywordsArr = explode(\',\', $BlockkeywordsStr);

            foreach ($BlockkeywordsArr as $k2 => $voo) {
                        
                if ( strpos($frame->data,trim($voo)) ){
                    $frame->data = str_replace($voo ,\'*\',$frame->data);
                }

            }

        Task::async(\'TalkTask\', \'UserToCustomerTalkLog\', [$data[\'from\'], $data[\'to\'], 1, $data[\'content\']]);

        $customer = Redis::get(\'user_fd\'.$data[\'to\']);

            if (empty($customer)) {
                //$autoReply = Redis::hget($data[\'content\']);

                CLog::info(\'talk: %s \', \'2222\');

                $server->push($frame->fd, json_encode([\'content\'=>\'这里是人工智能回复\',\'from\'=>$data[\'to\']]));
            }else{

                $server->push($customer, json_encode([\'content\'=>$data[\'content\'],\'from\'=>$data[\'to\']]));
                CLog::info(\'talk: %s \', \'Recv: \'.$customer.\'--\'. $data[\'content\'].\'--\'.$data[\'to\']);
            }

    }
    /**
     * @onClose()
     * @param Server $server
     * @param int    $fd
     */
    public function onClose(Server $server, int $fd): void
    {
        $res = Redis::del(\'user_fd\'.$fd);

        CLog::info(\'#\' . $fd. \'Redis:\' . $res);

        $server->close($fd);
    }

}

以上可以去掉 CLog::info(\'#\' . $fd. \'Redis:\' . $res);   主要是能在后台看到实时的情况

 

<?php

    $MyInfo = [\'avatar\'=>\'https://wx.qlogo.cn/mmopen/vi_32/NhCl8wDjCM0IoZLgjZNtwb8rN26jic4Rxbk8lc0HIfvP3FY6HuZOtrArW45eBnS6htsJ9uMYPC4lxoXYchtwQQA/132\',\'nickname\'=>\'黑锦鲤\',\'id\'=>66296];
    $ToInfo = [\'avatar\'=>\'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif\',\'nickname\'=>\'客服锦鲤\',\'id\'=>151];

?>

<!DOCTYPE html>
<html>
<head>
    <title>XST-app</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    <meta name="viewport" content="width=device-width, initial-scale=0.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
    <meta name="keywords" content="test" />
    <meta name="description" content="test" />
    <meta name="author" content="XST-APP" />
    <meta content="yes" name="apple-mobile-web-app-capable" />
    <meta content="black" name="apple-mobile-web-app-status-bar-style" />
    <meta content="telephone=no" name="format-detection" />
    <script type="text/javascript" src="./jquery-1.8.3.min.js"></script>
  <style type="text/css">
    body{background:url(/static/images/yuyin_bg.jpg);background-size:100%;}
    @media all and (min-width: 640px) {
        body,html,.wenwen-footer,.speak_window{width:640px!important;margin:0 auto}
        .speak_window,.wenwen-footer{left:50%!important;margin-left:-320px}
    }
    input,button{outline:none;}
    .wenwen-footer{width:100%;position:fixed;bottom:-5px;left:0;background:#fff;padding:3%;border-top:solid 1px #ddd;box-sizing:border-box;}
    .wenwen_btn,.wenwen_help{width:15%;text-align:center;}
    .wenwen_btn img,.wenwen_help img{height:40px;}
    .wenwen_text{height:40px;border-radius:5px;border:solid 1px #636162;box-sizing:border-box;width:66%;text-align:center;overflow:hidden;margin-left:2%;}
    .circle-button{padding:0 5px;}
    .wenwen_text .circle-button{font-size:14px;color:#666;line-height:38px;}
    .write_box{background:#fff;width:100%;height:40px;line-height:40px;}
    .write_box input{height:40px;padding:0 5px;line-height:40px;width:100%;box-sizing:border-box;border:0;}
    .wenwen_help button{width:95%;background:#42929d;color:#fff;border-radius:5px;border:0;height:40px;}
    #wenwen{height:100%;}
    .speak_window{overflow-y:scroll;height:100%;width:100%;position:fixed;top:50px;left:0;}
    .speak_box{margin-bottom:70px;padding:10px;}
    .question,.answer{margin-bottom:1rem;}
    .question{text-align:right;}
    .question>div{display:inline-block;}
    .left{float:left;}
    .right{float:right;}
    .clear{clear:both;}
    .heard_img{height:60px;width:60px;border-radius:5px;overflow:hidden;background:#ddd;}
    .heard_img img{width:100%;height:100%}
    .question_text,.answer_text{box-sizing:border-box;position:relative;display:table-cell;min-height:60px;}
    .question_text{padding-right:20px;}
    .answer_text{padding-left:20px;}
    .question_text p,.answer_text p{border-radius:10px;padding:.5rem;margin:0;font-size:14px;line-height:28px;box-sizing:border-box;vertical-align:middle;display:table-cell;height:30px;word-wrap:break-word;}
    .answer_text p{background:#fff;}
    .question_text p{background:#42929d;color:#fff;text-align:left;}
    .question_text i,.answer_text i{width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;position:absolute;top:25px;}
    .answer_text i{border-right:10px solid #fff;left:10px;}
    .question_text i{border-left:10px solid #42929d;right:10px;}
    .answer_text p a{color:#42929d;display:inline-block;}
    .write_list{position:absolute;left:0;width:100%;background:#fff;border-top:solid 1px #ddd;padding:5px;line-height:30px;}
  </style>
</head>

<body>
<div id="header" class="head">
        <div class="wrap">
                <i class="menu_back"><a href="javascript:history.go(-1);"></a></i>
                <div class="title">
                        <span class="title_d"><p>与   <?php echo $ToInfo[\'nickname\']; ?>   的聊天</p></span>
                        <div class="clear"></div>
                </div>
                <!--i class="menu_share"></i-->
        </div>
</div>

<input type="hidden" name="myemail" id="myemail" value="<?php echo $MyInfo[\'id\']; ?>" />
<input type="hidden" name="mynickname" id="mynickname" value="<?php echo $MyInfo[\'nickname\']; ?>" />
<input type="hidden" name="myavatar" id="myavatar" value="<?php echo $MyInfo[\'avatar\']; ?>" />

<input type="hidden" name="toemail" id="toemail" value="<?php echo $ToInfo[\'id\']; ?>" />
<input type="hidden" name="tonickname" id="tonickname" value="<?php echo $ToInfo[\'nickname\']; ?>" />
<input type="hidden" name="toavatar" id="toavatar" value="<?php echo $ToInfo[\'avatar\']; ?>" />

<!-- 对话内容 -->
<div class="speak_window">
    <div class="speak_box">

    </div>
</div>


<!-- 内容输入-->
<div class="wenwen-footer">
    <div class="wenwen_btn left"><img src="/static/images/jp_btn.png"></div>
    <div class="wenwen_text left">
        <div class="write_box"><input type="text" class="left" onKeyUp="keyup()" maxlength="100" placeholder="请输入信息(100字以内)..." /></div>   
    </div>
    <div class="wenwen_help right">
            <button onClick="send()" class="right">发送</button>
    </div>
    <div style="opacity:0;" class="clear"></div>
</div>


<script type="text/javascript">
    if ("WebSocket" in window){
        var ws = new WebSocket("ws://47.111.253.56:18308/echo");
        ws.onopen = function(){
            console.log("握手成功");
            var myemail = $("#myemail").val();
            var mynickname = $("#mynickname").val();
            var toemail = $("#toemail").val();
            var arr = {"flag":"init","from":myemail,"to":toemail,"content":mynickname+\'需要帮助\'};
            var str = JSON.stringify(arr);
            alert(str)
            ws.send(str);
        };
        ws.onmessage = function(e){
            var toemail = $("#toemail").val();
            var toavatar = $("#toavatar").val();

            if (e.data) {
                console.log(e.data);

                var obj = JSON.parse(e.data);
                
                console.log(obj.from);
                console.log(toemail);
                console.log(obj.content);
                //但同时与两个人聊天时,可能两个人的消息都会出现在当前窗口,所以此处加个判断,此窗口只接收当前聊天对象的消息,其他则忽略
                //if(obj.from === toemail){
                    var ans  = \'<div class="answer"><div class="heard_img left"><img src="\'+toavatar+\'"></div>\';
                        ans += \'<div class="answer_text"><p>\'+obj.content+\'</p><i></i>\';
                        ans += \'</div></div>\';
                        $(\'.speak_box\').append(ans);
                        for_bottom();
                //} 
            };
            
        };
        ws.onerror = function(){
            console.log("error");
            var  str  = \'<div class="question">\';
            str += \'<div class="heard_img right"><img src="/static/images/xitong.jpg"></div>\';
            str += \'<div class="question_text clear"><p>聊天服务器出现异常,暂时无法提供服务。</p><i></i>\';
            str += \'</div></div>\';
            $(\'.speak_box\').append(str);
            $(\'.write_box input\').val(\'\');
            $(\'.write_box input\').focus();
            autoWidth();
            for_bottom();
        };

        function send() {
            var content = $(\'.write_box input\').val();
            if(content === \'\'){
                alert(\'请输入消息!\');
                $(\'.write_box input\').focus();
            }else{
                    var toemail = $("#toemail").val();
                    var myemail = $("#myemail").val();
                    var myavatar = $("#myavatar").val();
                    var arr = {"flag":"msg","to":toemail,"from":myemail,"content":content};
                    var msg = JSON.stringify(arr);
                    console.log(msg);
                    ws.send(msg);    
                    var  str  = \'<div class="question">\';
                    str += \'<div class="heard_img right"><img src="\'+myavatar+\'"></div>\';
                    str += \'<div class="question_text clear"><p>\'+content+\'</p><i></i>\';
                    str += \'</div></div>\';
                $(\'.speak_box\').append(str);
                $(\'.write_box input\').val(\'\');
                $(\'.write_box input\').focus();
                autoWidth();
                for_bottom();
            }
        
        }
    }else{
        alert("您的浏览器不支持 WebSocket!");
    }
           
    function for_bottom(){
    var speak_height = $(\'.speak_box\').height();
    $(\'.speak_box,.speak_window\').animate({scrollTop:speak_height},500);
    }
    
    function autoWidth(){
    $(\'.question_text\').css(\'max-width\',$(\'.question\').width()-60);
    }
    
    autoWidth();
    
</script>

</body>
</html>

 

 这个客户端就是为了测试。

 

分类:

技术点:

相关文章:

  • 2021-12-19
  • 2021-11-11
  • 2021-11-16
  • 2021-06-27
  • 2021-08-13
  • 2021-07-02
  • 2021-12-09
猜你喜欢
  • 2021-05-18
  • 2021-11-14
  • 2021-03-10
  • 2021-05-21
  • 2022-12-23
  • 2021-05-25
相关资源
相似解决方案