diff --git a/app/common/controller/MessageNotificationsController.php b/app/common/controller/MessageNotificationsController.php new file mode 100644 index 0000000..4e475eb --- /dev/null +++ b/app/common/controller/MessageNotificationsController.php @@ -0,0 +1,33 @@ +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; + // } +} \ No newline at end of file diff --git a/app/common/controller/MessageUserStatusController.php b/app/common/controller/MessageUserStatusController.php new file mode 100644 index 0000000..302aec4 --- /dev/null +++ b/app/common/controller/MessageUserStatusController.php @@ -0,0 +1,33 @@ +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; + // } +} \ No newline at end of file diff --git a/app/common/logic/MessageNotificationsLogic.php b/app/common/logic/MessageNotificationsLogic.php new file mode 100644 index 0000000..b0a1429 --- /dev/null +++ b/app/common/logic/MessageNotificationsLogic.php @@ -0,0 +1,17 @@ +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(); + } +} \ No newline at end of file diff --git a/app/common/service/MessageUserStatusService.php b/app/common/service/MessageUserStatusService.php new file mode 100644 index 0000000..f04e8b5 --- /dev/null +++ b/app/common/service/MessageUserStatusService.php @@ -0,0 +1,31 @@ +validator; + } +} \ No newline at end of file diff --git a/app/common/utils/WsEvents.php b/app/common/utils/WsEvents.php index 0916078..c5642c0 100644 --- a/app/common/utils/WsEvents.php +++ b/app/common/utils/WsEvents.php @@ -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], diff --git a/app/common/validate/MessageNotificationsValidate.php b/app/common/validate/MessageNotificationsValidate.php new file mode 100644 index 0000000..c5dd6e1 --- /dev/null +++ b/app/common/validate/MessageNotificationsValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/common/validate/MessageUserStatusValidate.php b/app/common/validate/MessageUserStatusValidate.php new file mode 100644 index 0000000..647cebd --- /dev/null +++ b/app/common/validate/MessageUserStatusValidate.php @@ -0,0 +1,29 @@ + [ + + ], + + 'update' => [ + + ] + ]; +} \ No newline at end of file diff --git a/app/controller/IndexController.php b/app/controller/IndexController.php index e7ae182..3651926 100644 --- a/app/controller/IndexController.php +++ b/app/controller/IndexController.php @@ -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); } } \ No newline at end of file diff --git a/app/functions.php b/app/functions.php index 299bad4..d9bb411 100644 --- a/app/functions.php +++ b/app/functions.php @@ -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; + } } \ No newline at end of file