Branch 加入 同步畫面
修面包廂 分頁問題
調整 is_online 改成圖示顯示
This commit is contained in:
allen.yan 2025-08-03 16:20:50 +08:00
parent 948d21667b
commit 3228031528
8 changed files with 227 additions and 15 deletions

View File

@ -0,0 +1,68 @@
<?php
namespace App\Jobs;
use App\Models\TextAd;
use App\Services\SqliteExportService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ExportSqliteTextAdJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 600;
protected ?int $branchId;
public function __construct(?int $branchId = null)
{
$this->branchId = $branchId;
}
public function handle()
{
$sqlitePath = storage_path('app/database/tempTextAd.sqlite');
if (!file_exists(dirname($sqlitePath))) {
mkdir(dirname($sqlitePath), 0755, true);
}
if (!file_exists($sqlitePath)) {
file_put_contents($sqlitePath, '');
}
$connectionName = 'tempsqlite_' . md5($sqlitePath . microtime());
config(["database.connections.{$connectionName}" => [
'driver' => 'sqlite',
'database' => $sqlitePath,
'prefix' => '',
]]);
$exporter = new SqliteExportService($connectionName);
$exporter->exportMultiple([
'text_ads' => [
'query' => fn () => DB::table('text_ads'),
'tableSchema' => function (Blueprint $table) {
$table->id();
$table->string('content')->comment('廣告內容');
$table->enum('color', ['black','white', 'red', 'green','blue'])->default('black')->comment('顯示顏色');
$table->integer('duration')->default(1)->comment('播放間隔時間(分鐘)');
$table->boolean('is_active')->default(true); // 啟用狀態
$table->timestamps();
},
'transformer' => fn ($row) => [
'content' => $row->content,
'color' => $row->color,
'duration' => $row->duration,
'is_active' => $row->is_active,
'created_at' => $row->created_at,
'updated_at' => $row->updated_at,
],
],
]);
SendSqliteFileJob::dispatch($sqlitePath, $this->branchId);
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Livewire\Modals;
use App\Models\Branch;
use Livewire\Component;
use App\Jobs\ExportSqliteBranchJob;
use App\Jobs\ExportSqliteSongJob;
use App\Jobs\ExportSqliteFavoriteJob;
use App\Jobs\ExportSqliteTextAdJob;
use App\Jobs\ExportSqliteUserJob;
use WireUi\Traits\WireUiActions;
class BranchSyncModal extends Component
{
use WireUiActions;
protected $listeners = [
'openModal','closeModal'
];
public int $branch_id;
public string $branch_name;
public bool $syncBranch = false;
public bool $syncSong = false;
public bool $syncFavorite = false;
public bool $syncTextAds = false;
public bool $syncUser = false;
public bool $showModal = false;
public function openModal($branch_id)
{
$this->branch_id = $branch_id;
$this->branch_name = Branch::find($branch_id)->name;
$this->reset('syncBranch', 'syncSong', 'syncFavorite', 'syncTextAds', 'syncUser');
$this->showModal = true;
}
public function closeModal()
{
$this->showModal = false;
}
public function save()
{
if ($this->syncBranch) {
ExportSqliteBranchJob::dispatch($this->branch_id);
}
if ($this->syncSong) {
ExportSqliteSongJob::dispatch($this->branch_id);
}
if ($this->syncFavorite) {
ExportSqliteFavoriteJob::dispatch($this->branch_id);
}
if($this->syncTextAds){
ExportSqliteTextAdJob::dispatch($this->branch_id);
}
if ($this->syncUser) {
ExportSqliteUserJob::dispatch(true, $this->branch_id);
}
$this->notification()->send([
'icon' => 'success',
'title' => '同步任務',
'description' => '已加入排程',
]);
$this->showModal = false;
}
public function render()
{
return view('livewire.modals.branch-sync-modal');
}
}

View File

@ -202,10 +202,10 @@ final class BranchTable extends PowerGridComponent
{
$actions = [];
$actions[] = Button::add('room-synchronous')
->slot('包廂同步')
->slot('分店中控同步')
->icon('solid-cog')
->class('inline-flex items-center gap-1 px-3 py-1 rounded bg-amber-200 text-black')
->dispatch('synchronous.' . $this->tableName, ['branch_id' => $row->id]);
->dispatchTo('modals.branch-sync-modal','openModal', ['branch_id' => $row->id]);
if ($this->canEdit) {
$actions[] =Button::add('edit')
->slot(__('branches.edit'))

View File

@ -62,7 +62,12 @@ final class RoomStatusLogTable extends PowerGridComponent
->add('user_name', function (RoomStatusLog $model){
return $model->user?->name;
})
->add('is_online')
->add('is_online_img', fn ($model) =>
[
$model->is_online ? 'check-circle' : 'x-circle' => [
'text-color' => $model->is_online ? 'text-green-600' : 'text-red-600',
],
])
->add('status_str',function (RoomStatusLog $model){
return $model->status->labelPowergridFilter();
})
@ -80,7 +85,7 @@ final class RoomStatusLogTable extends PowerGridComponent
$column[]=Column::make(__('room-status-log.branch'), 'branch_name');
$column[]=Column::make(__('room-status-log.room'), 'room_name');
$column[]=Column::make(__('room-status-log.user'), 'user_name');
$column[]=Column::make(__('room-status-log.is_online'), 'is_online');
$column[]=Column::make(__('room-status-log.is_online'), 'is_online_img')->template();
$column[]=Column::make(__('room-status-log.status'), 'status_str');
$column[]=Column::make(__('room-status-log.started_at'), 'started_at');
$column[]=Column::make(__('room-status-log.ended_at'), 'ended_at');
@ -89,6 +94,17 @@ final class RoomStatusLogTable extends PowerGridComponent
$column[]=Column::make(__('room-status-log.created_at'), 'created_at');
return $column;
}
public function rowTemplates(): array
{
return [
'check-circle' => '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 {{ text-color }}">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>',
'x-circle' => '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 {{ text-color }}">
<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>',
];
}
public function filters(): array
{

View File

@ -18,6 +18,7 @@ use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Traits\WithExport;
use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable;
use Livewire\Attributes\On;
use Livewire\Attributes\Url;
use WireUi\Traits\WireUiActions;
final class RoomTable extends PowerGridComponent
@ -26,7 +27,7 @@ final class RoomTable extends PowerGridComponent
public string $tableName = 'room-table';
public bool $canDownload;
public bool $canDelect;
#[Url]
public ?int $selectedBranchId = null;
public ?string $external_ip= "";
@ -38,8 +39,7 @@ final class RoomTable extends PowerGridComponent
$this->canDownload=Auth::user()?->can('room-delete') ?? false;
$this->canDelect = Auth::user()?->can('room-delete') ?? false;
$branch = Branch::first();
$this->selectedBranchId = $branch?->id;
$this->external_ip = $branch?->external_ip;
$this->selectChanged($branch?->id,"", "");
}
public function setUp(): array
@ -57,7 +57,7 @@ final class RoomTable extends PowerGridComponent
->showToggleColumns();
$header->includeViewOnTop('livewire.headers.room');
$actions[]=$header;
$actions[]=PowerGrid::footer()->pageName('selectedBranchId')->showPerPage()->showRecordCount();
$actions[]=PowerGrid::footer()->showPerPage()->showRecordCount();
return $actions;
}
public function header(): array
@ -83,10 +83,6 @@ final class RoomTable extends PowerGridComponent
return $query;
}
public function updatedSelectedBranchId($value)
{
$this->resetPage(); // 重設分頁
}
public function relationSearch(): array
{
@ -102,7 +98,12 @@ final class RoomTable extends PowerGridComponent
return $model->type->labelPowergridFilter();
})
->add('name')
->add('is_online', fn ($model) => $model->is_online===true ? '在線' : '斷線')
->add('is_online_img', fn ($model) => [
$model->is_online ? 'check-circle' : 'x-circle' => [
'text-color' => $model->is_online ? 'text-green-600' : 'text-red-600',
],
]
)
->add('status_str',function (Room $model){
return $model->status->labelPowergridFilter();
})
@ -118,7 +119,7 @@ final class RoomTable extends PowerGridComponent
$column[]=Column::make(__('rooms.floor'), 'floor')->sortable()->searchable();
$column[]=Column::make(__('rooms.type'), 'type_str','room.type')->sortable()->searchable();
$column[]=Column::make(__('rooms.name'), 'name')->sortable()->searchable();
$column[]=Column::make(__('rooms.isOnline'), 'is_online');
$column[]=Column::make(__('rooms.isOnline'), 'is_online_img')->template();
$column[]=Column::make(__('rooms.status'), 'status_str','room.status')->sortable()->searchable()->hidden(true, false);
$column[]=Column::make(__('rooms.started_at'), 'str_started_at', 'started_at')->sortable()->hidden(true, false);
$column[]=Column::make(__('rooms.ended_at'), 'str_ended_at', 'ended_at')->sortable()->hidden(true, false);
@ -127,6 +128,17 @@ final class RoomTable extends PowerGridComponent
return $column;
}
public function rowTemplates(): array
{
return [
'check-circle' => '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 {{ text-color }}">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>',
'x-circle' => '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 {{ text-color }}">
<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>',
];
}
public function filters(): array
{
@ -153,11 +165,12 @@ final class RoomTable extends PowerGridComponent
#[On('selectChanged')]
public function selectChanged($value,$fieldName, $modelId): void
{
//dd($value,$fieldName, $modelId);
if($fieldName == 'selectedBranchId'){
$this->selectedBranchId=$value;
$branch = Branch::find($this->selectedBranchId);
$this->external_ip=$branch->external_ip;
$this->resetPage(); // 重設分頁
}
}
#[On('deleteRoom')]

View File

@ -42,6 +42,12 @@ class Room extends Model
'started_at',
'ended_at',
];
protected $attributes = [
'type' => \App\Enums\RoomType::Unset,
'floor' => 1,
'is_online' => false,
'status' => \App\Enums\RoomStatus::Error,
];
protected $hidden = [
'internal_ip',

View File

@ -3,5 +3,6 @@
<x-wireui:notifications/>
<livewire:tables.branch-table />
<livewire:forms.branch-form />
<livewire:modals.branch-sync-modal />
<livewire:import-datas.branch />
</x-layouts.admin>

View File

@ -0,0 +1,32 @@
<x-wireui:modal id="room-sync-modal" wire:model.defer="showModal" persistent>
<x-wireui:card class="border border-gray-200">
<x-slot name="action">
<button class="cursor-pointer p-1 rounded-full focus:outline-none focus:outline-hidden focus:ring-2 focus:ring-secondary-200 text-secondary-300"
wire:click="closeModal"
tabindex="-1"
>
<x-dynamic-component
:component="WireUi::component('icon')"
name="x-mark"
class="w-5 h-5"
/>
</button>
</x-slot>
<x-slot name="title">
{{ $branch_name ?? '未選擇' }} 分店中控同步
</x-slot>
<div class="grid grid-cols-1 gap-2 mb-4">
<x-wireui:checkbox id="sync-song" wire:model="syncSong" label="歌曲資料 Song" />
<x-wireui:checkbox id="sync-favorite" wire:model="syncFavorite" label="收藏資料 Favorite" />
<x-wireui:checkbox id="sync-text-ads" wire:model="syncTextAds" label="跑馬燈 TextAd" />
<x-wireui:checkbox id="sync-user" wire:model="syncUser" label="使用者資料 User" />
<x-wireui:checkbox id="sync-branch" wire:model="syncBranch" label="分店資料 Branch" />
</div>
<x-slot name="footer">
<div class="flex justify-between w-full">
<x-wireui:button flat label="{{__('branches.cancel')}}" wire:click="closeModal" />
<x-wireui:button primary label="{{__('branches.submit')}}" wire:click="save" />
</div>
</x-slot>
</x-wireui:card>
</x-wireui:modal>