mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 18:02:55 +00:00
feat: 优化消息推送逻辑
This commit is contained in:
parent
ee9b6248bb
commit
c668340661
@ -4,8 +4,10 @@ namespace App\Http\Middleware;
|
||||
|
||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||
|
||||
use App\Module\Base;
|
||||
use App\Module\Doo;
|
||||
use App\Services\RequestContext;
|
||||
use Cache;
|
||||
use Closure;
|
||||
|
||||
class WebApi
|
||||
@ -29,6 +31,12 @@ class WebApi
|
||||
// 加载Doo类
|
||||
Doo::load();
|
||||
|
||||
// 记录 PC 端活跃时间
|
||||
$userid = Doo::userId();
|
||||
if ($userid > 0 && Base::isPc()) {
|
||||
Cache::put("user_pc_active:{$userid}", time(), 60);
|
||||
}
|
||||
|
||||
// 解密请求内容
|
||||
$encrypt = Doo::pgpParseStr($request->header('encrypt'));
|
||||
if ($request->isMethod('post')) {
|
||||
|
||||
@ -10,6 +10,7 @@ namespace App\Models;
|
||||
* @property string $key
|
||||
* @property string|null $fd
|
||||
* @property string|null $path
|
||||
* @property string|null $platform 平台类型:android, ios, win, mac, web
|
||||
* @property int|null $userid
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
@ -27,6 +28,7 @@ namespace App\Models;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereKey($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket wherePath($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket wherePlatform($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|WebSocket whereUserid($value)
|
||||
* @mixin \Eloquent
|
||||
|
||||
@ -1827,6 +1827,19 @@ class Base
|
||||
return $platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是PC端(包括 Electron 桌面端和 Web 浏览器)
|
||||
* @param string|null $platform 平台类型,不传则自动获取
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPc($platform = null)
|
||||
{
|
||||
if ($platform === null) {
|
||||
$platform = self::platform();
|
||||
}
|
||||
return in_array($platform, ['win', 'mac', 'web']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是App移动端
|
||||
* @return bool
|
||||
|
||||
@ -64,7 +64,7 @@ class WebSocketService implements WebSocketHandlerInterface
|
||||
'ud' => $userid,
|
||||
],
|
||||
]));
|
||||
$this->userOn($fd, $userid);
|
||||
$this->userOn($fd, $userid, $get['platform']);
|
||||
} else {
|
||||
// 用户不存在
|
||||
$server->push($fd, Base::array2json([
|
||||
@ -105,6 +105,11 @@ class WebSocketService implements WebSocketHandlerInterface
|
||||
|
||||
// 握手信息
|
||||
case 'handshake':
|
||||
// 更新 PC 端活跃时间
|
||||
$row = WebSocket::whereFd($frame->fd)->first();
|
||||
if ($row && Base::isPc($row->platform)) {
|
||||
Cache::put("user_pc_active:{$row->userid}", time(), 60);
|
||||
}
|
||||
break;
|
||||
|
||||
// 访问状态
|
||||
@ -166,17 +171,27 @@ class WebSocketService implements WebSocketHandlerInterface
|
||||
* 用户上线
|
||||
* @param $fd
|
||||
* @param $userid
|
||||
* @param $platform
|
||||
* @return void
|
||||
*/
|
||||
private function userOn($fd, $userid)
|
||||
private function userOn($fd, $userid, $platform = 'web')
|
||||
{
|
||||
// 校验平台类型
|
||||
if (!in_array($platform, ['android', 'ios', 'win', 'mac', 'web'])) {
|
||||
$platform = 'web';
|
||||
}
|
||||
WebSocket::updateInsert([
|
||||
'key' => md5($fd . '@' . $userid)
|
||||
], [
|
||||
'fd' => $fd,
|
||||
'userid' => $userid,
|
||||
'platform' => $platform,
|
||||
]);
|
||||
OnlineData::online($userid);
|
||||
// PC 端上线时更新活跃时间
|
||||
if (Base::isPc($platform)) {
|
||||
Cache::put("user_pc_active:{$userid}", time(), 60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
namespace App\Tasks;
|
||||
|
||||
use App\Models\UmengAlias;
|
||||
use App\Models\WebSocketDialogMsgRead;
|
||||
use App\Module\Base;
|
||||
use Cache;
|
||||
use Hhxsv5\LaravelS\Swoole\Task\Task;
|
||||
|
||||
/**
|
||||
* 推送友盟消息
|
||||
@ -11,6 +14,7 @@ class PushUmengMsg extends AbstractTask
|
||||
{
|
||||
protected $userid = 0;
|
||||
protected $array = [];
|
||||
protected $endPush = []; // 需要在 end() 方法中处理的延迟推送列表
|
||||
|
||||
/**
|
||||
* @param array|int $userid
|
||||
@ -32,11 +36,68 @@ class PushUmengMsg extends AbstractTask
|
||||
if ($setting['push'] !== 'open') {
|
||||
return;
|
||||
}
|
||||
UmengAlias::pushMsgToUserid($this->userid, $this->array);
|
||||
|
||||
// 消息ID
|
||||
$msgId = isset($this->array['id']) ? intval($this->array['id']) : 0;
|
||||
|
||||
// 处理用户列表
|
||||
$userids = is_array($this->userid) ? $this->userid : [$this->userid];
|
||||
$directPushUsers = []; // 直接推送的用户
|
||||
$delayedPushUsers = []; // 需要延迟推送的用户
|
||||
|
||||
foreach ($userids as $uid) {
|
||||
if ($this->getDelay() > 0) {
|
||||
// 已经延迟过,检查消息是否已读
|
||||
if ($msgId > 0) {
|
||||
$isRead = WebSocketDialogMsgRead::whereMsgId($msgId)
|
||||
->whereUserid($uid)
|
||||
->whereNotNull('read_at')
|
||||
->exists();
|
||||
if ($isRead) {
|
||||
// 已读,跳过推送
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 未读或无法判断,执行推送
|
||||
$directPushUsers[] = $uid;
|
||||
} else {
|
||||
// 首次推送,检查 PC 端是否活跃
|
||||
$lastActive = Cache::get("user_pc_active:{$uid}");
|
||||
$isPcActive = $lastActive && (time() - $lastActive) < 60;
|
||||
|
||||
if ($isPcActive) {
|
||||
// PC 端活跃,需要延迟推送
|
||||
$delayedPushUsers[] = $uid;
|
||||
} else {
|
||||
// PC 端不活跃,直接推送
|
||||
$directPushUsers[] = $uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 直接推送
|
||||
if ($directPushUsers) {
|
||||
UmengAlias::pushMsgToUserid($directPushUsers, $this->array);
|
||||
}
|
||||
|
||||
// 创建延迟推送任务
|
||||
if ($delayedPushUsers) {
|
||||
$this->endPush[] = [
|
||||
'userid' => $delayedPushUsers,
|
||||
'array' => $this->array,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function end()
|
||||
{
|
||||
|
||||
if (empty($this->endPush)) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->endPush as $item) {
|
||||
$task = new PushUmengMsg($item['userid'], $item['array']);
|
||||
$task->delay(10);
|
||||
Task::deliver($task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,6 +211,10 @@ class WebSocketDialogMsgTask extends AbstractTask
|
||||
'description' => "MID:{$msg->id}",
|
||||
'seconds' => 3600,
|
||||
'badge' => 1,
|
||||
'extra' => [
|
||||
'dialog_id' => $msg->dialog_id,
|
||||
'msg_id' => $msg->id,
|
||||
]
|
||||
];
|
||||
$this->endArray[] = new PushUmengMsg($uids->toArray(), $umengMsg);
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddWebSocketsPlatform extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('web_sockets', function (Blueprint $table) {
|
||||
$table->string('platform', 20)->nullable()->default('')->after('path')->comment('平台类型:android, ios, win, mac, web');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('web_sockets', function (Blueprint $table) {
|
||||
$table->dropColumn('platform');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
2
resources/assets/js/store/actions.js
vendored
2
resources/assets/js/store/actions.js
vendored
@ -4484,7 +4484,7 @@ export default {
|
||||
let url = $A.mainUrl('ws');
|
||||
url = url.replace("https://", "wss://");
|
||||
url = url.replace("http://", "ws://");
|
||||
url += `?action=web&token=${state.userToken}&language=${languageName}`;
|
||||
url += `?action=web&token=${state.userToken}&language=${languageName}&platform=${$A.Platform}`;
|
||||
//
|
||||
const wgLog = $A.openLog;
|
||||
const wsRandom = $A.randomString(16);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user