优化 红包 页面

This commit is contained in:
2026-04-21 15:10:41 +08:00
parent 916f4c5aa6
commit 96a449d94b
4 changed files with 154 additions and 25 deletions
+29 -5
View File
@@ -1,10 +1,10 @@
<?php
/**
* 文件功能:红包领取成功广播事件(广播至领取者私有频道)
* 文件功能:红包领取成功广播事件(广播至房间与领取者私有频道)
*
* 触发时机:RedPacketController::claim() 成功后广播,
* 前端收到后弹出 Toast 通知展示到账金额
* 房间内在线用户收到后实时刷新剩余份数,领取者本人可同步收到到账提示
*
* @author ChatRoom Laravel
*
@@ -15,11 +15,18 @@ namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
/**
* 类功能:广播礼包被领取后的实时状态
*
* 统一向房间频道推送剩余份数变化,同时向领取者私有频道推送到账结果,
* 让红包弹窗与用户提示保持一致。
*/
class RedPacketClaimed implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
@@ -28,32 +35,49 @@ class RedPacketClaimed implements ShouldBroadcastNow
* @param User $claimer 领取用户
* @param int $amount 领取金额
* @param int $envelopeId 红包 ID
* @param int $roomId 房间 ID
* @param int $remainingCount 剩余份数
* @param string $type 红包类型
*/
public function __construct(
public readonly User $claimer,
public readonly int $amount,
public readonly int $envelopeId,
public readonly int $roomId,
public readonly int $remainingCount,
public readonly string $type = 'gold',
) {}
/**
* 广播至领取者私有频道。
* 广播至房间频道与领取者私有频道。
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [new PrivateChannel('user.'.$this->claimer->id)];
return [
new PresenceChannel('room.'.$this->roomId),
new PrivateChannel('user.'.$this->claimer->id),
];
}
/**
* 广播领取结果与剩余份数。
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
$typeLabel = $this->type === 'exp' ? '经验' : '金币';
return [
'envelope_id' => $this->envelopeId,
'claimer_id' => $this->claimer->id,
'claimer_username' => $this->claimer->username,
'amount' => $this->amount,
'message' => "🧧 成功抢到 {$this->amount} 金币礼包!",
'remaining_count' => $this->remainingCount,
'type' => $this->type,
'message' => "🧧 成功抢到 {$this->amount} {$typeLabel}礼包!",
];
}
+19 -2
View File
@@ -32,6 +32,11 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
/**
* 类功能:处理聊天室礼包的发包、查状态与抢包流程
*
* 负责礼包主记录创建、Redis 拆包金额管理、领取入账以及实时广播。
*/
class RedPacketController extends Controller
{
/** 礼包固定总数量 */
@@ -307,8 +312,19 @@ class RedPacketController extends Controller
return response()->json(['status' => 'error', 'message' => '您已经领过这个礼包了'], 422);
}
// 广播领取事件(给自己的私有频道,前端弹 Toast)
broadcast(new RedPacketClaimed($user, $amount, $envelope->id));
// 重新读取红包统计,确保广播与响应使用的是最新剩余份数。
$envelope->refresh();
$remainingCount = $envelope->remainingCount();
// 广播领取事件:房间内所有在线用户实时刷新剩余份数,领取者本人同步收到到账通知。
broadcast(new RedPacketClaimed(
claimer: $user,
amount: $amount,
envelopeId: $envelope->id,
roomId: $envelope->room_id,
remainingCount: $remainingCount,
type: $envelopeType,
));
// 在聊天室发送领取播报(所有人可见)
$typeLabel = $envelopeType === 'exp' ? '经验' : '金币';
@@ -335,6 +351,7 @@ class RedPacketController extends Controller
'status' => 'success',
'amount' => $amount,
'type' => $envelopeType,
'remaining_count' => $remainingCount,
'message' => "🧧 恭喜!您抢到了 {$amount} {$typeLabel}!当前{$typeLabel}{$balanceNow}",
]);
}