作者 何书鹏

新订单提醒

... ... @@ -24,6 +24,15 @@
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!--新订单提醒-->
<li class="hidden-xs orders" data-uid="{$Think.session.admin.id}">
<a href="#" >
<i class="fa" style="font-size:14px;"></i>
新订单
<span class="pull-right-container"> <small class="badge pull-right bg-red" id="order_nums">0</small></span>
</a>
</li>
<li class="hidden-xs">
<a href="__PUBLIC__" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i> {:__('Home')}</a>
</li>
... ...
... ... @@ -17,7 +17,7 @@ use think\Validate;
*/
class User extends Api
{
protected $noNeedLogin = ['third','joinUs','developLogin'];
protected $noNeedLogin = ['third','joinUs','developLogin','ceshi'];
protected $noNeedRight = '*';
public function _initialize()
... ... @@ -815,4 +815,25 @@ class User extends Api
$this->error($this->auth->getError());
}
}
/**
* 测试
*/
public function ceshi(){
$push_api_url = request()->domain().":2121/";
$post_data = array(
'type' => 'publish',
'content' => '这个是推送的测试数据',
'to' => '',
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $push_api_url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, array("Expect:"));
$return = curl_exec ( $ch );
curl_close ( $ch );
}
}
... ...
<?php
namespace app\socketio\controller;
use Workerman\Worker;
use Workerman\Timer;
use PHPSocketIO\SocketIO;
use Workerman\Protocols\Http\Request;
use Workerman\Connection\TcpConnection;
class Server
{
// 全局数组保存uid在线数据
private $uidConnectionMap = array();
// 记录最后一次广播的在线用户数
private $last_online_count = 0;
// 记录最后一次广播的在线页面数
private $last_online_page_count = 0;
public function index(){
header("Access-Control-Allow-Origin: *");
// PHPSocketIO服务
$sender_io = new SocketIO(2120);
// 客户端发起连接事件时,设置连接socket的各种事件回调
$sender_io->on('connection', function($socket){
// 当客户端发来登录事件时触发
$socket->on('login', function ($uid)use($socket){
// global $uidConnectionMap, $last_online_count, $last_online_page_count;
// 已经登录过了
if(isset($socket->uid)){
return;
}
// 更新对应uid的在线数据
$uid = (string)$uid;
if(!isset($this->uidConnectionMap[$uid]))
{
$this->uidConnectionMap[$uid] = 0;
}
// 这个uid有++$uidConnectionMap[$uid]个socket连接
++$this->uidConnectionMap[$uid];
// 将这个连接加入到uid分组,方便针对uid推送数据
$socket->join($uid);
$socket->uid = $uid;
// 更新这个socket对应页面的在线数据
$socket->emit('update_online_count', "当前<b>{$this->last_online_count}</b>人在线,共打开<b>{$this->last_online_page_count}</b>个页面");
});
// 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
$socket->on('disconnect', function () use($socket) {
if(!isset($socket->uid))
{
return;
}
// global $uidConnectionMap, $sender_io;
// 将uid的在线socket数减一
if(--$this->uidConnectionMap[$socket->uid] <= 0)
{
unset($this->uidConnectionMap[$socket->uid]);
}
});
});
// 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
$sender_io->on('workerStart', function() use ($sender_io) {
// 监听一个http端口
$inner_http_worker = new Worker('http://0.0.0.0:2121');
// 当http客户端发来数据时触发
$inner_http_worker->onMessage = function(TcpConnection $http_connection, Request $request) use ($sender_io) {
// global $uidConnectionMap;
$post = $request->post();
$post = $post ? $post : $request->get();
// 推送数据的url格式 type=publish&to=uid&content=xxxx
switch(@$post['type']){
case 'publish':
// global $sender_io;
$to = @$post['to'];
$post['content'] = htmlspecialchars(@$post['content']);
// 有指定uid则向uid所在socket组发送数据
if($to){
$sender_io->to($to)->emit('new_msg', $post['content']);
// 否则向所有uid推送数据
}else{
$sender_io->emit('new_msg', @$post['content']);
}
// http接口返回,如果用户离线socket返回fail
if($to && !isset($this->uidConnectionMap[$to])){
return $http_connection->send('offline');
}else{
return $http_connection->send('ok');
}
}
return $http_connection->send('fail');
};
// 执行监听
$inner_http_worker->listen();
// 一个定时器,定时向所有uid推送当前uid在线数及在线页面数
Timer::add(1, function() use ($sender_io) {
// global $uidConnectionMap, $sender_io, $last_online_count, $last_online_page_count;
$online_count_now = count($this->uidConnectionMap);
$online_page_count_now = array_sum($this->uidConnectionMap);
// 只有在客户端在线数变化了才广播,减少不必要的客户端通讯
if($this->last_online_count != $online_count_now || $this->last_online_page_count != $online_page_count_now)
{
$sender_io->emit('update_online_count', "当前<b>{$online_count_now}</b>人在线,共打开<b>{$online_page_count_now}</b>个页面");
$this->last_online_count = $online_count_now;
$this->last_online_page_count = $online_page_count_now;
}
});
});
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
}
}
\ No newline at end of file
... ...
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], function ($, undefined, Backend, undefined, AdminLTE, Form) {
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form','https://cdn.bootcss.com/socket.io/2.1.1/socket.io.js'], function ($, undefined, Backend, undefined, AdminLTE, Form,io) {
var Controller = {
index: function () {
//双击重新加载页面
... ... @@ -359,6 +359,26 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
$(window).resize();
// 新订单提醒
$('.orders').click(function(){
$('#order_nums').html(0);
Backend.api.addtabs('litestore/litestoreorder');
})
$(document).ready(function () {
var uid=$('.orders').attr('data-uid');
// 连接服务端
var socket = io('http://'+document.domain+':2120');
// 连接后登录
socket.on('connect', function(){
socket.emit('login', uid);
});
// 后端推送来消息时
socket.on('new_msg', function(msg){
Toastr.success(msg);
$('#order_nums').html($('#order_nums').html()*1+1);
});
});
},
login: function () {
var lastlogin = localStorage.getItem("lastlogin");
... ...
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','socketio/Server/index');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
\ No newline at end of file
... ...