Files
chatroom/app/Events/BannerNotification.php
lkddi 5c53b8cf2f 功能:window.chatBanner 全局大卡片公共组件
前端:
- window.chatBanner.show(options) 全局 API,完全自定义:
  icon/title/name/body/sub/gradient/titleColor/autoClose/buttons
- window.chatBanner.close(id) 关闭指定 banner
- showFriendBanner / showAppointmentBanner 均改用 chatBanner 实现
- setupBannerNotification() 监听私有+房间频道的 BannerNotification 事件

后端:
- BannerNotification 事件(ShouldBroadcastNow),支持 user/room 双目标
- BannerBroadcastController(仅超级管理员路由,三层中间件保护)
- 内容字段 strip_tags 净化防 XSS,按钮 action 白名单校验

安全:
- window.chatBanner.show() 被人控制台调用只影响自己,无法推给他人
- HTTP 入口 POST /admin/banner/broadcast 仅超管可访问
2026-03-01 01:28:23 +08:00

98 lines
3.0 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:通用大卡片通知广播事件
*
* 可向指定用户私有频道或房间所有人Presence 频道)推送全屏大卡片通知。
* 前端通过 window.chatBanner.show(options) 渲染,支持完全自定义。
*
* 使用示例(后端):
*
* // 推给单个用户
* broadcast(new BannerNotification(
* target: 'user',
* targetId: 'lkddi',
* options: [
* 'icon' => '💚📩',
* 'title' => '好友申请',
* 'name' => 'lkddi1',
* 'body' => '将你加为好友了!',
* 'gradient' => ['#1e3a5f', '#1d4ed8', '#0891b2'],
* 'autoClose' => 0,
* 'buttons' => [
* ['label' => ' 回加好友', 'color' => '#10b981', 'action' => 'add_friend', 'actionData' => 'lkddi1'],
* ['label' => '稍后再说', 'color' => 'rgba(255,255,255,0.15)', 'action' => 'close'],
* ],
* ]
* ));
*
* // 推给整个房间
* broadcast(new BannerNotification(target: 'room', targetId: 1, options: [...] ));
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Events;
use Illuminate\Broadcasting\Channel;
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 BannerNotification implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* 构造通用大卡片通知事件。
*
* @param string $target 推送目标类型:'user'(私有频道)| 'room'(房间全员)
* @param string|int $targetId 目标 ID用户名user或 房间 IDroom
* @param array<string, mixed> $options 前端 chatBanner.show() 选项(详见文件顶部注释)
*/
public function __construct(
public readonly string $target,
public readonly string|int $targetId,
public readonly array $options = [],
) {}
/**
* 根据 $target 决定广播到私有频道还是 Presence 频道。
*/
public function broadcastOn(): Channel
{
return match ($this->target) {
'user' => new PrivateChannel('user.'.$this->targetId),
'room' => new PresenceChannel('room.'.$this->targetId),
default => new PrivateChannel('user.'.$this->targetId),
};
}
/**
* 指定广播事件名称,供前端 .listen('.BannerNotification') 匹配。
*/
public function broadcastAs(): string
{
return 'BannerNotification';
}
/**
* 广播负载:传递完整的 options 给前端渲染。
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return [
'target' => $this->target,
'target_id' => $this->targetId,
'options' => $this->options,
];
}
}