消息推送
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace app\common\controller;
|
||||
|
||||
use app\common\controller\BaseController;
|
||||
use app\common\traits\crud\CrudControllerTrait;
|
||||
use app\common\service\MessageNotificationsService;
|
||||
|
||||
class MessageNotificationsController extends BaseController
|
||||
{
|
||||
use CrudControllerTrait;
|
||||
|
||||
protected $service;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->service = new MessageNotificationsService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表页数据格式化
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
// protected function indexFormat($data)
|
||||
// {
|
||||
// if (isset($data['created_at']))
|
||||
// $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
|
||||
// if (isset($data['updated_at']))
|
||||
// $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
|
||||
// return $data;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace app\common\controller;
|
||||
|
||||
use app\common\controller\BaseController;
|
||||
use app\common\traits\crud\CrudControllerTrait;
|
||||
use app\common\service\MessageUserStatusService;
|
||||
|
||||
class MessageUserStatusController extends BaseController
|
||||
{
|
||||
use CrudControllerTrait;
|
||||
|
||||
protected $service;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->service = new MessageUserStatusService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表页数据格式化
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
// protected function indexFormat($data)
|
||||
// {
|
||||
// if (isset($data['created_at']))
|
||||
// $data['created_at'] = date('Y-m-d H:i:s', $data['created_at']);
|
||||
// if (isset($data['updated_at']))
|
||||
// $data['updated_at'] = date('Y-m-d H:i:s', $data['updated_at']);
|
||||
// return $data;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\logic;
|
||||
|
||||
use app\common\traits\crud\CrudLogicTrait;
|
||||
use app\common\model\MessageNotifications;
|
||||
|
||||
class MessageNotificationsLogic
|
||||
{
|
||||
use CrudLogicTrait;
|
||||
|
||||
/**
|
||||
* 指定当前要操作的模型
|
||||
*/
|
||||
protected string $modelClass = MessageNotifications::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\logic;
|
||||
|
||||
use app\common\traits\crud\CrudLogicTrait;
|
||||
use app\common\model\MessageUserStatus;
|
||||
|
||||
class MessageUserStatusLogic
|
||||
{
|
||||
use CrudLogicTrait;
|
||||
|
||||
/**
|
||||
* 指定当前要操作的模型
|
||||
*/
|
||||
protected string $modelClass = MessageUserStatus::class;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class MessageNotifications extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connection = 'mysql';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'message_notifications';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* 允许自动填充模型字段
|
||||
*/
|
||||
protected $fillable = ['id', 'msg_no', 'sender_id', 'sender_type', 'recipient', 'title', 'content', 'scene', 'created_at'];
|
||||
|
||||
/**
|
||||
* 不允许自动填充模型字段
|
||||
*/
|
||||
protected $guarded = [];
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class MessageUserStatus extends Model
|
||||
{
|
||||
/**
|
||||
* The connection name for the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connection = 'mysql';
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'message_user_status';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
|
||||
protected $dateFormat = 'U';
|
||||
|
||||
/**
|
||||
* 允许自动填充模型字段
|
||||
*/
|
||||
protected $fillable = ['id', 'msg_id', 'uid', 'status', 'read_at'];
|
||||
|
||||
/**
|
||||
* 不允许自动填充模型字段
|
||||
*/
|
||||
protected $guarded = [];
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\validate\MessageNotificationsValidate;
|
||||
use app\common\traits\crud\CrudServiceTrait;
|
||||
use app\common\model\MessageNotifications;
|
||||
use app\common\model\User;
|
||||
use support\Db;
|
||||
|
||||
class MessageNotificationsService
|
||||
{
|
||||
|
||||
use CrudServiceTrait;
|
||||
|
||||
/**
|
||||
* 指定当前要操作的模型
|
||||
*/
|
||||
protected string $modelClass = MessageNotifications::class;
|
||||
|
||||
/**
|
||||
* 验证器
|
||||
*/
|
||||
protected $validator = MessageNotificationsValidate::class;
|
||||
|
||||
/**
|
||||
* 获取验证器
|
||||
*/
|
||||
public function getValidator()
|
||||
{
|
||||
return new $this->validator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建一条消息
|
||||
*/
|
||||
public function createMessage(array $data): int
|
||||
{
|
||||
$msgId = Db::table('message_notifications')->insertGetId([
|
||||
'msg_no' => generateMsgId(),
|
||||
'sender_id' => $data['sender_id'],
|
||||
'sender_type' => $data['sender_type'],
|
||||
'title' => $data['title'],
|
||||
'content' => $data['content'],
|
||||
'scene' => $data['scene'],
|
||||
'recipient' => $data['recipient'],
|
||||
'created_at' => time(),
|
||||
]);
|
||||
|
||||
return $msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量插入用户消息状态
|
||||
*/
|
||||
public function addUserStatus(int $msgId, array $uids)
|
||||
{
|
||||
$rows = [];
|
||||
foreach ($uids as $uid) {
|
||||
$rows[] = [
|
||||
'msg_id' => $msgId,
|
||||
'uid' => $uid,
|
||||
'status' => 0,
|
||||
'read_at' => null
|
||||
];
|
||||
}
|
||||
if ($rows) {
|
||||
Db::table('message_user_status')->insert($rows);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记消息已读
|
||||
*/
|
||||
public function markAsRead(array|string $msgIds, int $uid)
|
||||
{
|
||||
$query = Db::table('message_user_status')->where('uid', $uid);
|
||||
if (is_array($msgIds)) {
|
||||
$query->whereIn('msg_id', $msgIds);
|
||||
}
|
||||
return $query->update([
|
||||
'status' => 1,
|
||||
'read_at' => time()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有用户ID
|
||||
*/
|
||||
public function getAllUserIds(): array
|
||||
{
|
||||
return User::where('status', 1)->pluck('id')->toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\validate\MessageUserStatusValidate;
|
||||
use app\common\traits\crud\CrudServiceTrait;
|
||||
use app\common\model\MessageUserStatus;
|
||||
|
||||
class MessageUserStatusService
|
||||
{
|
||||
|
||||
use CrudServiceTrait;
|
||||
|
||||
/**
|
||||
* 指定当前要操作的模型
|
||||
*/
|
||||
protected string $modelClass = MessageUserStatus::class;
|
||||
|
||||
/**
|
||||
* 验证器
|
||||
*/
|
||||
protected $validator = MessageUserStatusValidate::class;
|
||||
|
||||
/**
|
||||
* 获取验证器
|
||||
*/
|
||||
public function getValidator()
|
||||
{
|
||||
return new $this->validator;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace app\common\utils;
|
||||
|
||||
use GatewayWorker\Lib\Gateway;
|
||||
use app\common\utils\WsResponse;
|
||||
use app\common\service\MessageNotificationsService;
|
||||
|
||||
class WsEvents
|
||||
{
|
||||
@@ -72,17 +73,17 @@ class WsEvents
|
||||
return;
|
||||
}
|
||||
|
||||
// // 连接是否满足条件
|
||||
// if ($payload['server']['HTTP_ORIGIN'] != 'https://wstool.js.org') {
|
||||
// flg('[x] [TOKEN认证] HTTP_ORIGIN不满足条件', false);
|
||||
// Gateway::sendToClient($client_id, WsResponse::error(
|
||||
// 'system.auth',
|
||||
// 1001,
|
||||
// '[x] [TOKEN认证] HTTP_ORIGIN不满足条件'
|
||||
// ));
|
||||
// Gateway::closeClient($client_id);
|
||||
// return;
|
||||
// }
|
||||
// 连接是否满足条件
|
||||
if ($payload['server']['HTTP_ORIGIN'] != 'https://wstool.js.org') {
|
||||
flg('[x] [TOKEN认证] HTTP_ORIGIN不满足条件', false);
|
||||
Gateway::sendToClient($client_id, WsResponse::error(
|
||||
'system.auth',
|
||||
1001,
|
||||
'[x] [TOKEN认证] HTTP_ORIGIN不满足条件'
|
||||
));
|
||||
Gateway::closeClient($client_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// 签名检查
|
||||
if (!isset($payload['get']['token'])) {
|
||||
@@ -136,11 +137,6 @@ class WsEvents
|
||||
// ================= 消息通知事件 =================
|
||||
/**
|
||||
* 管理端主动推送通知
|
||||
* data = [
|
||||
* 'to_uids' => [uid1, uid2], // 可选,为空表示全员
|
||||
* 'title' => '标题',
|
||||
* 'content' => '内容',
|
||||
* ]
|
||||
*/
|
||||
public function notifyPush(?string $traceId)
|
||||
{
|
||||
@@ -158,7 +154,20 @@ class WsEvents
|
||||
return;
|
||||
}
|
||||
|
||||
$msgId = rand(1000, 9999); // 生成消息ID,可用数据库存储
|
||||
// 写消息
|
||||
$msgService = new MessageNotificationsService();
|
||||
$msgId = $msgService->createMessage([
|
||||
'sender_id' => $this->eventData['sender_id'] ?? 0,
|
||||
'sender_type' => $this->eventData['sender_type'] ?? 'system',
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'scene' => $this->eventData['scene'] ?? 0,
|
||||
'recipient' => $this->eventData['to_uids'] ? implode(',', $this->eventData['to_uids']) : '',
|
||||
]);
|
||||
|
||||
// 写用户状态
|
||||
$uids = !empty($toUids) ? $toUids : $msgService->getAllUserIds();
|
||||
$msgService->addUserStatus($msgId, $uids);
|
||||
|
||||
$payload = WsResponse::success('notify.push', [
|
||||
'msg_id' => $msgId,
|
||||
@@ -181,18 +190,18 @@ class WsEvents
|
||||
Gateway::sendToClient($this->clientId, WsResponse::success(
|
||||
'notify.push.result',
|
||||
['msg_id' => $msgId],
|
||||
$traceId
|
||||
$traceId,
|
||||
'消息发送成功'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端标记通知已读
|
||||
* data = ['msg_ids' => [1,2,3]]
|
||||
*/
|
||||
public function notifyRead(?string $traceId)
|
||||
{
|
||||
$msgIds = $this->eventData['msg_ids'] ?? [];
|
||||
if (empty($msgIds)) {
|
||||
$msgIds = $this->eventData['msg_ids'];
|
||||
if (!is_array($msgIds) && $msgIds !== 'all') {
|
||||
Gateway::sendToClient($this->clientId, WsResponse::error(
|
||||
'notify.read',
|
||||
400,
|
||||
@@ -201,6 +210,11 @@ class WsEvents
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新消息为已读
|
||||
$msgService = new MessageNotificationsService();
|
||||
$msgService->markAsRead($msgIds, Gateway::getUidByClientId($this->clientId));
|
||||
|
||||
Gateway::sendToClient($this->clientId, WsResponse::success(
|
||||
'notify.read.result',
|
||||
['msg_ids' => $msgIds],
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class MessageNotificationsValidate extends Validate
|
||||
{
|
||||
// 规则
|
||||
protected $rule = [
|
||||
|
||||
];
|
||||
|
||||
// 提示
|
||||
protected $message = [
|
||||
|
||||
];
|
||||
|
||||
// 场景
|
||||
protected $scene = [
|
||||
'store' => [
|
||||
|
||||
],
|
||||
|
||||
'update' => [
|
||||
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class MessageUserStatusValidate extends Validate
|
||||
{
|
||||
// 规则
|
||||
protected $rule = [
|
||||
|
||||
];
|
||||
|
||||
// 提示
|
||||
protected $message = [
|
||||
|
||||
];
|
||||
|
||||
// 场景
|
||||
protected $scene = [
|
||||
'store' => [
|
||||
|
||||
],
|
||||
|
||||
'update' => [
|
||||
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -77,25 +77,25 @@ class IndexController
|
||||
$options = [
|
||||
'controller' => [
|
||||
'module' => 'common',
|
||||
'name' => 'resources'
|
||||
'name' => 'message_notifications'
|
||||
],
|
||||
'model' => [
|
||||
'module' => 'common',
|
||||
'name' => 'resources'
|
||||
'name' => 'message_notifications'
|
||||
],
|
||||
'service' => [
|
||||
'module' => 'common',
|
||||
'name' => 'resources'
|
||||
'name' => 'message_notifications'
|
||||
],
|
||||
'logic' => [
|
||||
'module' => 'common',
|
||||
'name' => 'resources'
|
||||
'name' => 'message_notifications'
|
||||
],
|
||||
'validate' => [
|
||||
'module' => 'common',
|
||||
'name' => 'resources'
|
||||
'name' => 'message_notifications'
|
||||
],
|
||||
'table' => 'resources'
|
||||
'table' => 'message_notifications'
|
||||
];
|
||||
|
||||
$result = (new Generate($options))->doGenerate();
|
||||
@@ -106,21 +106,11 @@ class IndexController
|
||||
public function test()
|
||||
{
|
||||
|
||||
// $data = [
|
||||
// 'code' => 'GD20250703-1DC80',
|
||||
// 'category' => '账号类问题',
|
||||
// 'content' => '这是一条测试工单内容。'
|
||||
// ];
|
||||
// \app\common\utils\email\MailSend::send('mzl@hnxinyouhe.com', '【XYH】新的工单提醒', replaceTpl($data, 'work_order'));
|
||||
$service = new \app\common\service\MessageNotificationsService();
|
||||
$udis = $service->getAllUserIds();
|
||||
|
||||
// $options = [
|
||||
// 'corp_id' => 3,
|
||||
// 'user_id' => 666
|
||||
// ];
|
||||
// \Webman\RedisQueue\Redis::send('perm-agt', $options);
|
||||
var_dump($udis);
|
||||
|
||||
$res = Cache::delete("user_resources_74_fdesk");
|
||||
|
||||
return 22;
|
||||
return json($udis);
|
||||
}
|
||||
}
|
||||
@@ -283,4 +283,28 @@ if (!function_exists('normalizeRichText')) {
|
||||
// 替换所有空白实体为普通空格
|
||||
return preg_replace('/\s+/u', ' ', $result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成消息编号(唯一业务标识)
|
||||
* 格式:年月日时分秒 + 微秒 + 随机数
|
||||
* 例如:20250820175530987654321
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
if (!function_exists('generateMsgId')) {
|
||||
function generateMsgId(): string
|
||||
{
|
||||
// 时间部分(精确到微秒)
|
||||
$time = microtime(true);
|
||||
$micro = sprintf("%06d", ($time - floor($time)) * 1e6);
|
||||
$date = date('YmdHis', (int)$time);
|
||||
|
||||
// 随机部分(3位)
|
||||
$rand = mt_rand(100, 999);
|
||||
|
||||
// 拼接:日期时间 + 微秒 + 随机数
|
||||
return $date . $micro . $rand;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user