202508131749
Broadcast 加入發送公告
This commit is contained in:
parent
6c30932855
commit
5e146b344e
132
app/Livewire/Forms/BroadcastTestForm.php
Normal file
132
app/Livewire/Forms/BroadcastTestForm.php
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Forms;
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
use WireUi\Traits\WireUiActions;
|
||||||
|
use App\Models\Room;
|
||||||
|
use App\Models\BroadcastTemplate;
|
||||||
|
use App\Services\TcpSocketClient;
|
||||||
|
|
||||||
|
class BroadcastTestForm extends Component
|
||||||
|
{
|
||||||
|
use WireUiActions;
|
||||||
|
|
||||||
|
protected $listeners = ['openModal', 'closeModal'];
|
||||||
|
|
||||||
|
// 常數定義
|
||||||
|
private const ALL_ROOMS_VALUE = 'all';
|
||||||
|
private const RESERVED_VARIABLES = ['room_name', 'date', 'time'];
|
||||||
|
|
||||||
|
public bool $showModal = false;
|
||||||
|
public ?string $prefix = "";
|
||||||
|
public ?string $content = "";
|
||||||
|
public ?string $roomId = null;
|
||||||
|
public array $roomOptions = [];
|
||||||
|
public array $variables = [];
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$this->roomOptions = collect([
|
||||||
|
['name' => '全部', 'value' => self::ALL_ROOMS_VALUE],
|
||||||
|
])->merge(
|
||||||
|
Room::where('type', '!=', 'svr')->get()->map(fn ($room) => [
|
||||||
|
'name' => $room->type->value . $room->name,
|
||||||
|
'value' => $room->id,
|
||||||
|
])
|
||||||
|
)->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openModal($id = null)
|
||||||
|
{
|
||||||
|
$broadcast = BroadcastTemplate::findOrFail($id);
|
||||||
|
$this->parseVariables($broadcast->content);
|
||||||
|
$this->content = $broadcast->content;
|
||||||
|
$this->showModal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function closeModal()
|
||||||
|
{
|
||||||
|
$this->resetFields();
|
||||||
|
$this->showModal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseVariables(string $content): void
|
||||||
|
{
|
||||||
|
preg_match_all('/\*\*(\w+)\*\*/', $content, $matches);
|
||||||
|
$this->variables = [];
|
||||||
|
|
||||||
|
foreach ($matches[1] as $varName) {
|
||||||
|
if (!in_array($varName, self::RESERVED_VARIABLES, true)) {
|
||||||
|
$this->variables[$varName] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send()
|
||||||
|
{
|
||||||
|
$rooms = $this->roomId === self::ALL_ROOMS_VALUE
|
||||||
|
? Room::where('type', '!=', 'svr')
|
||||||
|
->where('is_online', 1) // 只發送給在線房間
|
||||||
|
->get()
|
||||||
|
: Room::where('id', $this->roomId)->get();
|
||||||
|
|
||||||
|
foreach ($rooms as $room) {
|
||||||
|
$message = $this->buildMessage($room);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$client = new TcpSocketClient($room->internal_ip, $room->port);
|
||||||
|
$client->send($this->prefix . $message);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->notification()->send([
|
||||||
|
'icon' => 'error',
|
||||||
|
'title' => '發送失敗',
|
||||||
|
'description' => "❌ 房間 {$room->name} 發送失敗:{$e->getMessage()}",
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notification()->send([
|
||||||
|
'icon' => 'success',
|
||||||
|
'title' => '發送完成',
|
||||||
|
'description' => $this->roomId === self::ALL_ROOMS_VALUE
|
||||||
|
? '✅ 已發送至所有包廂'
|
||||||
|
: "✅ 已發送至房間 {$rooms->first()->name}",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->resetFields();
|
||||||
|
$this->showModal = false;
|
||||||
|
$this->dispatch('pg:eventRefresh-text-ads-table');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildMessage(Room $room): string
|
||||||
|
{
|
||||||
|
$message = $this->content;
|
||||||
|
|
||||||
|
// 保留變數替換
|
||||||
|
$message = str_replace("**room_name**", $room->type->labels() . '.' . $room->name, $message);
|
||||||
|
$message = str_replace("**date**", now()->format('Y-m-d'), $message);
|
||||||
|
$message = str_replace("**time**", now()->format('H:i'), $message);
|
||||||
|
|
||||||
|
// 自訂變數替換
|
||||||
|
foreach ($this->variables as $key => $value) {
|
||||||
|
$message = str_replace("**{$key}**", $value, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resetFields(): void
|
||||||
|
{
|
||||||
|
$this->content = '';
|
||||||
|
$this->roomId = null;
|
||||||
|
$this->variables = [];
|
||||||
|
$this->prefix = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.forms.broadcast-test-form');
|
||||||
|
}
|
||||||
|
}
|
@ -181,6 +181,11 @@ final class BroadcastTemplateTable extends PowerGridComponent
|
|||||||
public function actions(BroadcastTemplate $row): array
|
public function actions(BroadcastTemplate $row): array
|
||||||
{
|
{
|
||||||
$actions = [];
|
$actions = [];
|
||||||
|
$actions[] = Button::add('text-ad-test')
|
||||||
|
->slot('發送')
|
||||||
|
->icon('solid-cog')
|
||||||
|
->class('inline-flex items-center gap-1 px-3 py-1 rounded bg-amber-200 text-black')
|
||||||
|
->dispatchTo('forms.broadcast-test-form', 'openModal', ['id' => $row->id]);
|
||||||
if ($this->canEdit) {
|
if ($this->canEdit) {
|
||||||
$actions[]=Button::add('edit')
|
$actions[]=Button::add('edit')
|
||||||
->slot(__('broadcast-templates.edit'))
|
->slot(__('broadcast-templates.edit'))
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
<x-wireui:notifications/>
|
<x-wireui:notifications/>
|
||||||
<livewire:tables.broadcast-template-table />
|
<livewire:tables.broadcast-template-table />
|
||||||
<livewire:forms.broadcast-template-form />
|
<livewire:forms.broadcast-template-form />
|
||||||
|
<livewire:forms.broadcast-test-form />
|
||||||
</x-layouts.admin>
|
</x-layouts.admin>
|
33
resources/views/livewire/forms/broadcast-test-form.blade.php
Normal file
33
resources/views/livewire/forms/broadcast-test-form.blade.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<x-wireui:modal-card title="發送" blur wire:model.defer="showModal">
|
||||||
|
<x-wireui:select
|
||||||
|
label="選擇房間"
|
||||||
|
wire:model.defer="roomId"
|
||||||
|
placeholder="請選擇房間"
|
||||||
|
:options="$roomOptions"
|
||||||
|
option-label="name"
|
||||||
|
option-value="value"
|
||||||
|
/>
|
||||||
|
<div class="space-y-2">
|
||||||
|
@foreach($variables as $varName => $value)
|
||||||
|
<x-wireui:input
|
||||||
|
label="{{ $varName }}"
|
||||||
|
wire:model.defer="variables.{{ $varName }}"
|
||||||
|
placeholder="請填入 {{ $varName }}"
|
||||||
|
/>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-700 bg-gray-100 p-3 rounded shadow">
|
||||||
|
<div class="font-semibold mb-1">將發送內容:</div>
|
||||||
|
<div>{{ $content }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<div class="flex justify-between w-full">
|
||||||
|
<x-wireui:button flat label="{{__('text_ads.cancel')}}" wire:click="closeModal" />
|
||||||
|
<x-wireui:button primary wire:click="send" primary label="立即發送" spinner />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-wireui:modal-card>
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user