定时任务
This commit is contained in:
parent
bf44e4abb4
commit
78ada91ff5
|
|
@ -6,6 +6,7 @@
|
||||||
namespace App\Controller\Admin;
|
namespace App\Controller\Admin;
|
||||||
|
|
||||||
use App\Controller\AbstractController;
|
use App\Controller\AbstractController;
|
||||||
|
use Hyperf\Contract\LengthAwarePaginatorInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
abstract class Base extends AbstractController
|
abstract class Base extends AbstractController
|
||||||
|
|
@ -15,6 +16,11 @@ abstract class Base extends AbstractController
|
||||||
return $this->request->getAttribute("account_id");
|
return $this->request->getAttribute("account_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function uuid(): string
|
||||||
|
{
|
||||||
|
return $this->account()['uuid'];
|
||||||
|
}
|
||||||
|
|
||||||
public function account()
|
public function account()
|
||||||
{
|
{
|
||||||
return $this->request->getAttribute("account");
|
return $this->request->getAttribute("account");
|
||||||
|
|
@ -23,34 +29,42 @@ abstract class Base extends AbstractController
|
||||||
/**
|
/**
|
||||||
* Author: cfn <cfn@leapy.cn>
|
* Author: cfn <cfn@leapy.cn>
|
||||||
* @param array|string $msg
|
* @param array|string $msg
|
||||||
* @param array|null $data
|
* @param array|LengthAwarePaginatorInterface|null $data
|
||||||
* @param $count
|
* @param null $count
|
||||||
* @param $summary
|
* @param null $summary
|
||||||
* @return ResponseInterface
|
* @return ResponseInterface
|
||||||
*/
|
*/
|
||||||
public function success(array|string $msg = "success", array|null $data = null, $count = null, $summary = null)
|
public function success(array|string $msg = "success", LengthAwarePaginatorInterface|array|null $data = null, $count = null, $summary = null)
|
||||||
{
|
{
|
||||||
if (!is_string($msg)) {
|
if (!is_string($msg)) {
|
||||||
$data = $msg;
|
$data = $msg;
|
||||||
$msg = "success";
|
$msg = "success";
|
||||||
}
|
}
|
||||||
|
if ($data instanceof LengthAwarePaginatorInterface) {
|
||||||
|
$count = $data->total();
|
||||||
|
$data = $data->items();
|
||||||
|
}
|
||||||
return $this->response(0, $msg, $data, $count, $summary);
|
return $this->response(0, $msg, $data, $count, $summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Author: cfn <cfn@leapy.cn>
|
* Author: cfn <cfn@leapy.cn>
|
||||||
* @param array|string $msg
|
* @param array|string $msg
|
||||||
* @param array|null $data
|
* @param LengthAwarePaginatorInterface|array|null $data
|
||||||
* @param $count
|
* @param null $count
|
||||||
* @param $summary
|
* @param null $summary
|
||||||
* @return ResponseInterface
|
* @return ResponseInterface
|
||||||
*/
|
*/
|
||||||
public function error(array|string $msg = "error", array|null $data = null, $count = null, $summary = null)
|
public function error(array|string $msg = "error", LengthAwarePaginatorInterface|array|null $data = null, $count = null, $summary = null)
|
||||||
{
|
{
|
||||||
if (!is_string($msg)) {
|
if (!is_string($msg)) {
|
||||||
$data = $msg;
|
$data = $msg;
|
||||||
$msg = "error";
|
$msg = "error";
|
||||||
}
|
}
|
||||||
|
if ($data instanceof LengthAwarePaginatorInterface) {
|
||||||
|
$count = $data->total();
|
||||||
|
$data = $data->items();
|
||||||
|
}
|
||||||
return $this->response(1, $msg, $data, $count, $summary);
|
return $this->response(1, $msg, $data, $count, $summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use App\Annotation\Auth;
|
||||||
use App\Event\LogEvent;
|
use App\Event\LogEvent;
|
||||||
use App\Model\Account;
|
use App\Model\Account;
|
||||||
use App\Model\AccountLog;
|
use App\Model\AccountLog;
|
||||||
|
use App\Model\Online;
|
||||||
use App\Utils\Param;
|
use App\Utils\Param;
|
||||||
use App\Utils\Str;
|
use App\Utils\Str;
|
||||||
use App\Utils\Token;
|
use App\Utils\Token;
|
||||||
|
|
@ -77,16 +78,17 @@ class Login extends Base
|
||||||
return $this->error("账号或者密码错误!");
|
return $this->error("账号或者密码错误!");
|
||||||
}
|
}
|
||||||
// 商户ID
|
// 商户ID
|
||||||
|
$uuid = Str::uuid();
|
||||||
$tData['account_id'] = $account['account_id'];
|
$tData['account_id'] = $account['account_id'];
|
||||||
$tData['account_type'] = $account['account_type'];
|
$tData['account_type'] = $account['account_type'];
|
||||||
$tData['belong_id'] = $account['belong_id'];
|
$tData['belong_id'] = $account['belong_id'];
|
||||||
$tData['username'] = $account['username'];
|
$tData['username'] = $account['username'];
|
||||||
$tData['master_flag'] = $account['master_flag'];
|
$tData['master_flag'] = $account['master_flag'];
|
||||||
|
$tData['uuid'] = $uuid;
|
||||||
|
|
||||||
$uuid = Str::uuid();
|
|
||||||
$token = Token::buildToken(['uuid' => $uuid, 'time' => time() + config("jwt.ttl")], config("jwt.ttl"));
|
$token = Token::buildToken(['uuid' => $uuid, 'time' => time() + config("jwt.ttl")], config("jwt.ttl"));
|
||||||
// 记录登录日志
|
// 记录登录日志
|
||||||
$this->eventDispatcher->dispatch(new LogEvent($tData, $uuid));
|
$this->eventDispatcher->dispatch(new LogEvent($tData));
|
||||||
// 根据账号所属角色缓存相应的权限数据
|
// 根据账号所属角色缓存相应的权限数据
|
||||||
$auths = Account::getAuths($account['account_id'], $account['account_type'], $account['master_flag']);
|
$auths = Account::getAuths($account['account_id'], $account['account_type'], $account['master_flag']);
|
||||||
$redis->set("AUTH:" . $account['account_id'], json_encode($auths));
|
$redis->set("AUTH:" . $account['account_id'], json_encode($auths));
|
||||||
|
|
@ -113,6 +115,13 @@ class Login extends Base
|
||||||
#[Auth(needAuth: false)]
|
#[Auth(needAuth: false)]
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
|
// 退出登录状态
|
||||||
|
$container = ApplicationContext::getContainer();
|
||||||
|
$redis = $container->get(\Hyperf\Redis\Redis::class);
|
||||||
|
$redis->del("USER:" . $this->uuid());
|
||||||
|
$redis->del("AUTH:" . $this->account()['account_id']);
|
||||||
|
// 设置离线
|
||||||
|
Online::leave($this->uuid());
|
||||||
return $this->success("登出成功");
|
return $this->success("登出成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ namespace App\Controller\Admin;
|
||||||
use App\Annotation\Auth;
|
use App\Annotation\Auth;
|
||||||
use App\Model\Menu as mModel;
|
use App\Model\Menu as mModel;
|
||||||
use App\Model\Dept as dModel;
|
use App\Model\Dept as dModel;
|
||||||
|
use App\Model\Online;
|
||||||
use App\Model\Online as oModel;
|
use App\Model\Online as oModel;
|
||||||
use App\Model\Role as rModel;
|
use App\Model\Role as rModel;
|
||||||
use App\Utils\AppInfoHelper;
|
use App\Utils\AppInfoHelper;
|
||||||
|
|
@ -18,6 +19,7 @@ use App\Utils\MemoryHelper;
|
||||||
use App\Utils\Param;
|
use App\Utils\Param;
|
||||||
use App\Utils\RedisInfoHelper;
|
use App\Utils\RedisInfoHelper;
|
||||||
use App\Utils\SystemHelper;
|
use App\Utils\SystemHelper;
|
||||||
|
use Hyperf\Context\ApplicationContext;
|
||||||
use Hyperf\HttpServer\Annotation\Controller;
|
use Hyperf\HttpServer\Annotation\Controller;
|
||||||
use Hyperf\HttpServer\Annotation\DeleteMapping;
|
use Hyperf\HttpServer\Annotation\DeleteMapping;
|
||||||
use Hyperf\HttpServer\Annotation\GetMapping;
|
use Hyperf\HttpServer\Annotation\GetMapping;
|
||||||
|
|
@ -30,6 +32,8 @@ use App\Model\Post as pModel;
|
||||||
use App\Request\Post as pRequest;
|
use App\Request\Post as pRequest;
|
||||||
use App\Model\Account as aModel;
|
use App\Model\Account as aModel;
|
||||||
use App\Request\Account as aRequest;
|
use App\Request\Account as aRequest;
|
||||||
|
use App\Model\Crontab as cModel;
|
||||||
|
use App\Model\CrontabLog as clModel;
|
||||||
|
|
||||||
#[Controller(prefix: "admin")]
|
#[Controller(prefix: "admin")]
|
||||||
class System extends Base
|
class System extends Base
|
||||||
|
|
@ -365,4 +369,66 @@ class System extends Base
|
||||||
}
|
}
|
||||||
return $this->success('在线用户', $paginate->items(), $paginate->total());
|
return $this->success('在线用户', $paginate->items(), $paginate->total());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[GetMapping(path: "online/quit")]
|
||||||
|
#[Auth(auth: "online:quit")]
|
||||||
|
public function onlineQuit()
|
||||||
|
{
|
||||||
|
$param = Param::only(['session_id' => '']);
|
||||||
|
// 退出登录状态
|
||||||
|
$online = Online::getByUuid($param['session_id']);
|
||||||
|
if (empty($online) || $online['status'] == 0) {
|
||||||
|
return $this->success("用户已不在线");
|
||||||
|
}
|
||||||
|
$container = ApplicationContext::getContainer();
|
||||||
|
$redis = $container->get(\Hyperf\Redis\Redis::class);
|
||||||
|
$redis->del("USER:" . $param['session_id']);
|
||||||
|
$redis->del("AUTH:" . $online['account_id']);
|
||||||
|
// 设置离线
|
||||||
|
Online::leave($param['session_id']);
|
||||||
|
return $this->success("强退成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[GetMapping(path: "crontab/list")]
|
||||||
|
#[Auth(auth: "crontab:list")]
|
||||||
|
public function crontabList()
|
||||||
|
{
|
||||||
|
$param = Param::only(['crontab_name', 'enable', 'limit' => 10]);
|
||||||
|
return $this->success("任务列表", cModel::list($param));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[GetMapping(path: "crontab/option")]
|
||||||
|
#[Auth(needAuth: false)]
|
||||||
|
public function crontabOption()
|
||||||
|
{
|
||||||
|
return $this->success("任务列表", cModel::options());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[PostMapping(path: "crontab/add")]
|
||||||
|
#[Auth(auth: "crontab:add")]
|
||||||
|
public function crontabAdd()
|
||||||
|
{
|
||||||
|
$data = Param::only(['crontab_name' => '', 'rule', 'callback', 'memo', 'singleton', 'params', 'skip_log', 'enable' => 1]);
|
||||||
|
$res = cModel::add($data);
|
||||||
|
return $res ? $this->success("操作成功") : $this->error("操作失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[PutMapping(path: "crontab/edit")]
|
||||||
|
#[Auth(auth: "crontab:edit")]
|
||||||
|
public function crontabEdit()
|
||||||
|
{
|
||||||
|
$data = Param::only(['crontab_id' => '', 'crontab_name' => '', 'rule', 'callback', 'memo', 'singleton', 'params', 'skip_log', 'enable' => 1]);
|
||||||
|
$res = cModel::edit($data);
|
||||||
|
return $res ? $this->success("操作成功") : $this->error("操作失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[DeleteMapping(path: "crontab/del")]
|
||||||
|
#[Auth(auth: "crontab:del")]
|
||||||
|
public function crontabDel()
|
||||||
|
{
|
||||||
|
$ids = $this->request->input("ids", "");
|
||||||
|
if (!$ids) return $this->error("操作失败");
|
||||||
|
$res = cModel::del($ids);
|
||||||
|
return $res ? $this->success("操作成功") : $this->error("操作失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,5 +7,5 @@ namespace App\Event;
|
||||||
|
|
||||||
class LogEvent
|
class LogEvent
|
||||||
{
|
{
|
||||||
public function __construct(public array $data, public string $uuid){}
|
public function __construct(public array $data){}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
use App\Model\Online;
|
||||||
|
use App\Utils\Token;
|
||||||
|
use Hyperf\Context\ApplicationContext;
|
||||||
|
use Hyperf\Contract\OnCloseInterface;
|
||||||
|
use Hyperf\Contract\OnMessageInterface;
|
||||||
|
use Hyperf\Contract\OnOpenInterface;
|
||||||
|
use Hyperf\WebSocketServer\Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户端socket
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
*/
|
||||||
|
class WebSocket implements OnMessageInterface, OnOpenInterface, OnCloseInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 连接关闭
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
* @param $server
|
||||||
|
* @param int $fd
|
||||||
|
* @param int $reactorId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onClose($server, int $fd, int $reactorId): void
|
||||||
|
{
|
||||||
|
$uuid = Context::get('uuid', "");
|
||||||
|
Online::leave($uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接时
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
* @param $server
|
||||||
|
* @param $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onOpen($server, $request): void
|
||||||
|
{
|
||||||
|
$token = $request->get['Authorization'];
|
||||||
|
$result = Token::parseToken(str_replace("Bearer ", "", $token));
|
||||||
|
|
||||||
|
$container = ApplicationContext::getContainer();
|
||||||
|
$redis = $container->get(\Hyperf\Redis\Redis::class);
|
||||||
|
$account = !empty($result) ? json_decode($redis->get("USER:" . $result['uuid']), true) : null;
|
||||||
|
if (!empty($account)) {
|
||||||
|
Online::live($result['uuid'], $request->fd);
|
||||||
|
Context::set('account', $account);
|
||||||
|
Context::set('uuid', $result['uuid']);
|
||||||
|
$server->push($request->fd, 'connection successful');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$server->push($request->fd, 'connection refused');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当接收到信息
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
* @param $server
|
||||||
|
* @param $frame
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onMessage($server, $frame): void
|
||||||
|
{
|
||||||
|
if (strtolower($frame->data) == "ping") {
|
||||||
|
$server->push($frame->fd, 'pong');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$server->push($frame->fd, 'Recv: ' . $frame->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Author: cfn <cfn@leapy.cn>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Model\Online;
|
||||||
|
|
||||||
|
class WebSocketServer
|
||||||
|
{
|
||||||
|
// 访问启动时,关闭之前的连接
|
||||||
|
public function onStart(): void
|
||||||
|
{
|
||||||
|
Online::closeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务关闭,关闭之前的连接
|
||||||
|
public function onShutdown(): void
|
||||||
|
{
|
||||||
|
Online::closeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ class LogHandleListener implements ListenerInterface
|
||||||
public function process(object $event): void
|
public function process(object $event): void
|
||||||
{
|
{
|
||||||
Online::insert([
|
Online::insert([
|
||||||
'session_id' => $event->uuid,
|
'session_id' => $event->data['uuid'],
|
||||||
'account_type' => $event->data['account_type'],
|
'account_type' => $event->data['account_type'],
|
||||||
'belong_id' => $event->data['belong_id'],
|
'belong_id' => $event->data['belong_id'],
|
||||||
'account_id' => $event->data['account_id'],
|
'account_id' => $event->data['account_id'],
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Middleware;
|
namespace App\Middleware;
|
||||||
|
|
||||||
|
use App\Model\Online;
|
||||||
use App\Utils\Token;
|
use App\Utils\Token;
|
||||||
use Hyperf\Context\ApplicationContext;
|
use Hyperf\Context\ApplicationContext;
|
||||||
use Hyperf\Context\Context;
|
use Hyperf\Context\Context;
|
||||||
|
|
@ -43,7 +44,13 @@ class JWTMiddleware implements MiddlewareInterface
|
||||||
try {
|
try {
|
||||||
$token = $request->getHeaderLine("Authorization", "");
|
$token = $request->getHeaderLine("Authorization", "");
|
||||||
$result = Token::parseToken(str_replace("Bearer ", "", $token));
|
$result = Token::parseToken(str_replace("Bearer ", "", $token));
|
||||||
$account = !empty($result) ? json_decode($redis->get("USER:" . $result['uuid']), true) : null;
|
if (!empty($result)) {
|
||||||
|
$user = $redis->get("USER:" . $result['uuid']);
|
||||||
|
if (!empty($user)) {
|
||||||
|
$account = json_decode($user, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 判断登录状态是否强退
|
||||||
if (!empty($account)) {
|
if (!empty($account)) {
|
||||||
// 是否登录
|
// 是否登录
|
||||||
$request = $request->withAttribute("isLogin", true);
|
$request = $request->withAttribute("isLogin", true);
|
||||||
|
|
@ -52,6 +59,8 @@ class JWTMiddleware implements MiddlewareInterface
|
||||||
$request = $request->withAttribute("account_id", $account['account_id']);
|
$request = $request->withAttribute("account_id", $account['account_id']);
|
||||||
// 基础信息
|
// 基础信息
|
||||||
$request = $request->withAttribute("account", $account);
|
$request = $request->withAttribute("account", $account);
|
||||||
|
// 如果账户离线恢复在线
|
||||||
|
Online::reLive($result['uuid']);
|
||||||
}
|
}
|
||||||
} catch (\Exception $exception) {
|
} catch (\Exception $exception) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $crontab_id
|
||||||
|
* @property string $crontab_name
|
||||||
|
* @property string $rule
|
||||||
|
* @property string $callback
|
||||||
|
* @property string $memo
|
||||||
|
* @property string $params
|
||||||
|
* @property int $enable
|
||||||
|
* @property int $singleton
|
||||||
|
* @property int $skip_log
|
||||||
|
* @property string $create_time
|
||||||
|
* @property string $update_time
|
||||||
|
* @property string $deleted_at
|
||||||
|
*/
|
||||||
|
class Crontab extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*/
|
||||||
|
protected ?string $table = 'crontab';
|
||||||
|
|
||||||
|
protected string $primaryKey = 'crontab_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*/
|
||||||
|
protected array $fillable = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast to native types.
|
||||||
|
*/
|
||||||
|
protected array $casts = ['crontab_id' => 'integer', 'enable' => 'integer', 'singleton' => 'integer', 'skip_log' => 'integer'];
|
||||||
|
|
||||||
|
public static function list(array $param)
|
||||||
|
{
|
||||||
|
return self::query()
|
||||||
|
->when(isset($param['enable']), function ($query) use ($param) {
|
||||||
|
$query->where('enable', $param['enable']);
|
||||||
|
})
|
||||||
|
->when(isset($param['crontab_name']), function ($query) use ($param) {
|
||||||
|
$query->where('crontab_name', 'like', '%' . $param['crontab_name'] . '%');
|
||||||
|
})
|
||||||
|
->select(['crontab_id', 'crontab_name', 'enable', 'singleton', 'skip_log', 'rule', 'callback', 'params', 'memo', 'create_time'])
|
||||||
|
->orderByDesc('crontab_id')
|
||||||
|
->paginate((int)$param['limit']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function options()
|
||||||
|
{
|
||||||
|
return self::query()
|
||||||
|
->orderByDesc('crontab_id')
|
||||||
|
->orderByDesc('crontab_id')
|
||||||
|
->select(['crontab_id', 'crontab_name'])
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $log_id
|
||||||
|
* @property int $crontab_id
|
||||||
|
* @property string $crontab_name
|
||||||
|
* @property string $callback
|
||||||
|
* @property string $duration
|
||||||
|
* @property int $status
|
||||||
|
* @property string $result
|
||||||
|
* @property string $create_time
|
||||||
|
* @property string $deleted_at
|
||||||
|
*/
|
||||||
|
class CrontabLog extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*/
|
||||||
|
protected ?string $table = 'crontab_log';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*/
|
||||||
|
protected array $fillable = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast to native types.
|
||||||
|
*/
|
||||||
|
protected array $casts = ['log_id' => 'integer', 'crontab_id' => 'integer', 'status' => 'integer'];
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Model;
|
namespace App\Model;
|
||||||
|
|
||||||
|
use App\Utils\Ip;
|
||||||
|
use Swoole\Http\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $online_id
|
* @property int $online_id
|
||||||
* @property string $session_id
|
* @property string $session_id
|
||||||
|
|
@ -50,6 +53,41 @@ class Online extends Model
|
||||||
->paginate((int)$param['limit']);
|
->paginate((int)$param['limit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function closeAll(): int
|
||||||
|
{
|
||||||
|
return self::where("status", 1)
|
||||||
|
->where("online_time", ">", date("Y-m-d H:i:s", time() - 24 * 60 * 60))
|
||||||
|
->update(['status' => 0, 'offline_time' => date("Y-m-d H:i:s")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function leave(string $uuid): int
|
||||||
|
{
|
||||||
|
return self::where('session_id', $uuid)
|
||||||
|
->update(['status' => 0, 'offline_time' => date("Y-m-d H:i:s")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function live(string $uuid, int $fd): int
|
||||||
|
{
|
||||||
|
return self::where("session_id", $uuid)
|
||||||
|
->where("status", 1)
|
||||||
|
->update(['fd' => $fd, 'update_time' => date("Y-m-d H:i:s")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function reLive(string $uuid): bool
|
||||||
|
{
|
||||||
|
$online = self::getByUuid($uuid);
|
||||||
|
if ($online['status'] == 0) {
|
||||||
|
return (bool)self::where("session_id", $uuid)
|
||||||
|
->update(['update_time' => date("Y-m-d H:i:s"), 'status' => 1]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getByUuid(string $uuid)
|
||||||
|
{
|
||||||
|
return self::where("session_id", $uuid)->first(['status', 'session_id', 'account_id']);
|
||||||
|
}
|
||||||
|
|
||||||
public function account()
|
public function account()
|
||||||
{
|
{
|
||||||
return $this->hasOne(Account::class, 'account_id', 'account_id');
|
return $this->hasOne(Account::class, 'account_id', 'account_id');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file is part of Hyperf.
|
* This file is part of Hyperf.
|
||||||
*
|
*
|
||||||
|
|
@ -9,8 +10,9 @@ declare(strict_types=1);
|
||||||
* @contact group@hyperf.io
|
* @contact group@hyperf.io
|
||||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Hyperf\Server\Event;
|
use Hyperf\Server\Event;
|
||||||
use Hyperf\Server\Server;
|
use Hyperf\Server\ServerInterface;
|
||||||
use Swoole\Constant;
|
use Swoole\Constant;
|
||||||
use function Hyperf\Support\env;
|
use function Hyperf\Support\env;
|
||||||
|
|
||||||
|
|
@ -19,9 +21,9 @@ return [
|
||||||
'servers' => [
|
'servers' => [
|
||||||
[
|
[
|
||||||
'name' => 'http',
|
'name' => 'http',
|
||||||
'type' => Server::SERVER_HTTP,
|
'type' => ServerInterface::SERVER_HTTP,
|
||||||
'host' => '0.0.0.0',
|
'host' => '0.0.0.0',
|
||||||
'port' => (int) env('APP_PORT'),
|
'port' => (int)env('APP_PORT', 9501),
|
||||||
'sock_type' => SWOOLE_SOCK_TCP,
|
'sock_type' => SWOOLE_SOCK_TCP,
|
||||||
'callbacks' => [
|
'callbacks' => [
|
||||||
Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
|
Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
|
||||||
|
|
@ -30,6 +32,20 @@ return [
|
||||||
'enable_request_lifecycle' => false,
|
'enable_request_lifecycle' => false,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'ws',
|
||||||
|
'type' => ServerInterface::SERVER_WEBSOCKET,
|
||||||
|
'host' => '0.0.0.0',
|
||||||
|
'port' => (int)env('WS_PORT', 9502),
|
||||||
|
'sock_type' => SWOOLE_SOCK_TCP,
|
||||||
|
'callbacks' => [
|
||||||
|
Event::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],
|
||||||
|
Event::ON_MESSAGE => [Hyperf\WebSocketServer\Server::class, 'onMessage'],
|
||||||
|
Event::ON_CLOSE => [Hyperf\WebSocketServer\Server::class, 'onClose'],
|
||||||
|
Event::ON_START => [App\Event\WebSocketServer::class, 'onStart'],
|
||||||
|
Event::ON_SHUTDOWN => [App\Event\WebSocketServer::class, 'onShutdown'],
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'settings' => [
|
'settings' => [
|
||||||
Constant::OPTION_ENABLE_COROUTINE => true,
|
Constant::OPTION_ENABLE_COROUTINE => true,
|
||||||
|
|
@ -47,6 +63,7 @@ return [
|
||||||
'enable_static_handler' => true,
|
'enable_static_handler' => true,
|
||||||
],
|
],
|
||||||
'callbacks' => [
|
'callbacks' => [
|
||||||
|
Event::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'],
|
||||||
Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
|
Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
|
||||||
Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
|
Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
|
||||||
Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
|
Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,7 @@ Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@i
|
||||||
Router::get('/favicon.ico', function () {
|
Router::get('/favicon.ico', function () {
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Router::addServer('ws', function () {
|
||||||
|
Router::get('/ws', 'App\Event\WebSocket');
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue