结婚/婚礼/离婚通知持久化:新增事件监听器自动写入聊天消息数据库,用户重新登录后可在历史记录中看到通知
This commit is contained in:
131
app/Listeners/SaveMarriageSystemMessage.php
Normal file
131
app/Listeners/SaveMarriageSystemMessage.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:婚姻系统消息监听器
|
||||
*
|
||||
* 监听 MarriageAccepted / WeddingCelebration / MarriageDivorced 三个事件,
|
||||
* 自动向聊天室推送并持久化系统消息(写入 Redis 缓存 + 落库 messages 表),
|
||||
* 使得用户重新登录时可在历史记录中看到这些通知。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\MarriageAccepted;
|
||||
use App\Events\MarriageDivorced;
|
||||
use App\Events\WeddingCelebration;
|
||||
use App\Jobs\SaveMessageJob;
|
||||
use App\Services\ChatStateService;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
|
||||
class SaveMarriageSystemMessage
|
||||
{
|
||||
/** 固定使用房间 1(大厅)。 */
|
||||
private const ROOM_ID = 1;
|
||||
|
||||
public function __construct(
|
||||
private readonly ChatStateService $chatState,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 注册所有监听的事件。
|
||||
*/
|
||||
public function subscribe(Dispatcher $events): void
|
||||
{
|
||||
$events->listen(MarriageAccepted::class, [static::class, 'onMarriageAccepted']);
|
||||
$events->listen(WeddingCelebration::class, [static::class, 'onWeddingCelebration']);
|
||||
$events->listen(MarriageDivorced::class, [static::class, 'onMarriageDivorced']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结婚成功 → 向全频道追加系统消息。
|
||||
*/
|
||||
public function onMarriageAccepted(MarriageAccepted $event): void
|
||||
{
|
||||
$marriage = $event->marriage;
|
||||
$marriage->loadMissing(['user:id,username', 'partner:id,username', 'ringItem:id,name,icon']);
|
||||
|
||||
$userName = $marriage->user?->username ?? '??';
|
||||
$partnerName = $marriage->partner?->username ?? '??';
|
||||
$ring = $marriage->ringItem?->name ?? '爱情之戒';
|
||||
|
||||
$content = "💍 喜讯!【{$userName}】与【{$partnerName}】在 {$ring} 的见证下正式结为伴侣,祝新婚快乐!";
|
||||
|
||||
$this->pushAndSave($content, '#ec4899');
|
||||
}
|
||||
|
||||
/**
|
||||
* 婚礼庆典触发 → 向全频道追加婚礼公告消息。
|
||||
*/
|
||||
public function onWeddingCelebration(WeddingCelebration $event): void
|
||||
{
|
||||
$ceremony = $event->ceremony;
|
||||
$marriage = $event->marriage;
|
||||
$marriage->loadMissing(['user:id,username', 'partner:id,username']);
|
||||
$ceremony->loadMissing('tier');
|
||||
|
||||
$userName = $marriage->user?->username ?? '??';
|
||||
$partnerName = $marriage->partner?->username ?? '??';
|
||||
$tierName = $ceremony->tier?->name ?? '婚礼';
|
||||
$tierIcon = $ceremony->tier?->icon ?? '🎊';
|
||||
$amount = number_format((int) $ceremony->total_amount);
|
||||
|
||||
$content = "{$tierIcon} 【{$userName}】与【{$partnerName}】举办了【{$tierName}】婚礼大典!"
|
||||
."总计 🪙{$amount} 金币红包已向全场分发,快去领取吧!";
|
||||
|
||||
$this->pushAndSave($content, '#f59e0b');
|
||||
}
|
||||
|
||||
/**
|
||||
* 离婚完成 → 向全频道追加离婚公告消息。
|
||||
*/
|
||||
public function onMarriageDivorced(MarriageDivorced $event): void
|
||||
{
|
||||
$marriage = $event->marriage;
|
||||
$marriage->loadMissing(['user:id,username', 'partner:id,username']);
|
||||
|
||||
$userName = $marriage->user?->username ?? '??';
|
||||
$partnerName = $marriage->partner?->username ?? '??';
|
||||
|
||||
$typeLabel = match ($marriage->divorce_type) {
|
||||
'forced' => '强制离婚',
|
||||
'auto' => '超时自动离婚',
|
||||
'admin' => '管理员强制解除',
|
||||
default => '协议离婚',
|
||||
};
|
||||
|
||||
$content = "💔 【{$userName}】与【{$partnerName}】已{$typeLabel},缘分已尽,各奔东西。";
|
||||
|
||||
$this->pushAndSave($content, '#6b7280');
|
||||
}
|
||||
|
||||
/**
|
||||
* 将系统消息推入 Redis 缓存并分发 SaveMessageJob 落库。
|
||||
*
|
||||
* @param string $content 消息正文
|
||||
* @param string $fontColor 字体颜色
|
||||
*/
|
||||
private function pushAndSave(string $content, string $fontColor): void
|
||||
{
|
||||
$msg = [
|
||||
'id' => $this->chatState->nextMessageId(self::ROOM_ID),
|
||||
'room_id' => self::ROOM_ID,
|
||||
'from_user' => '系统传音',
|
||||
'to_user' => '大家',
|
||||
'content' => $content,
|
||||
'is_secret' => false,
|
||||
'font_color' => $fontColor,
|
||||
'action' => '大声宣告',
|
||||
'sent_at' => now()->toDateTimeString(),
|
||||
];
|
||||
|
||||
// 推入 Redis(当前在线用户的 polling 会取到)
|
||||
$this->chatState->pushMessage(self::ROOM_ID, $msg);
|
||||
|
||||
// 落库(离线用户下次登录可在历史消息中看到)
|
||||
SaveMessageJob::dispatch($msg);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:应用服务提供者
|
||||
*
|
||||
* 负责注册和引导应用级服务:自定义 SMTP 配置动态加载、
|
||||
* 婚姻系统消息事件订阅者注册等。
|
||||
*/
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Listeners\SaveMarriageSystemMessage;
|
||||
use App\Models\Sysparam;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -22,11 +31,14 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
// 注册婚姻系统消息订阅者(结婚/婚礼/离婚通知写入聊天历史)
|
||||
Event::subscribe(SaveMarriageSystemMessage::class);
|
||||
|
||||
// 动态加载自定义 SMTP 配置 (如果有数据库则执行)
|
||||
try {
|
||||
if (Schema::hasTable('sysparam')) {
|
||||
$smtpConfig = Sysparam::where('alias', 'like', 'smtp_%')->pluck('body', 'alias');
|
||||
|
||||
|
||||
if ($smtpConfig->isNotEmpty() && $smtpConfig->get('smtp_host')) {
|
||||
Config::set('mail.default', 'smtp');
|
||||
Config::set('mail.mailers.smtp', [
|
||||
@@ -36,7 +48,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
'encryption' => $smtpConfig->get('smtp_encryption', 'ssl'),
|
||||
'username' => $smtpConfig->get('smtp_username'),
|
||||
'password' => $smtpConfig->get('smtp_password'),
|
||||
'timeout' => 10,
|
||||
'timeout' => 10,
|
||||
'local_domain' => env('MAIL_EHLO_DOMAIN'),
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user