加入 包廂控制紀錄
加入 設備紀錄 加入 歌曲庫 cache 列表 調整 包廂控制邏輯 調整 心跳封包邏輯 調整 驗証包廂狀態邏輯 20250606
This commit is contained in:
parent
42338c62b4
commit
3307c062ab
@ -30,7 +30,6 @@ class CheckRoomOnlineStatus extends Command
|
|||||||
|
|
||||||
if (!$latestStatus || $latestStatus->created_at < $threshold) {
|
if (!$latestStatus || $latestStatus->created_at < $threshold) {
|
||||||
$room->is_online = false;
|
$room->is_online = false;
|
||||||
$room->status = RoomStatus::Error;
|
|
||||||
$room->save();
|
$room->save();
|
||||||
$this->info("Room [{$room->name}] marked as offline (no recent MachineStatus)");
|
$this->info("Room [{$room->name}] marked as offline (no recent MachineStatus)");
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,6 @@ class RoomControlController extends Controller
|
|||||||
$room->internal_ip = $validated['room_ip'];
|
$room->internal_ip = $validated['room_ip'];
|
||||||
$room->port = 1000; // 預設值
|
$room->port = 1000; // 預設值
|
||||||
$room->is_online =1;
|
$room->is_online =1;
|
||||||
$room->status = RoomStatus::Closed;
|
|
||||||
$room->touch(); // 更新 updated_at
|
$room->touch(); // 更新 updated_at
|
||||||
$room->save();
|
$room->save();
|
||||||
|
|
||||||
@ -284,10 +283,6 @@ class RoomControlController extends Controller
|
|||||||
return ApiResponse::error('房間未設定 IP 或 Port');
|
return ApiResponse::error('房間未設定 IP 或 Port');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($room->status === RoomStatus::Error) {
|
|
||||||
return ApiResponse::error('房間目前處於錯誤狀態,無法操作');
|
|
||||||
}
|
|
||||||
|
|
||||||
$suffix = substr($room->name, -3) ?: $room->name;
|
$suffix = substr($room->name, -3) ?: $room->name;
|
||||||
$signal = match ($validated['command']) {
|
$signal = match ($validated['command']) {
|
||||||
'active' => 'O',
|
'active' => 'O',
|
||||||
|
@ -10,40 +10,26 @@ use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
|||||||
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||||
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||||
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||||
use PowerComponents\LivewirePowerGrid\Traits\WithExport;
|
|
||||||
use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable;
|
|
||||||
use Spatie\Activitylog\Models\Activity;
|
use Spatie\Activitylog\Models\Activity;
|
||||||
|
|
||||||
|
|
||||||
final class ActivityLogTable extends PowerGridComponent
|
final class ActivityLogTable extends PowerGridComponent
|
||||||
{
|
{
|
||||||
use WithExport;
|
|
||||||
public string $tableName = 'activity-log-table';
|
public string $tableName = 'activity-log-table';
|
||||||
public bool $canDownload;
|
|
||||||
|
|
||||||
public bool $showFilters = false;
|
public bool $showFilters = false;
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
config(['livewire-powergrid.filter' => 'outside']);
|
config(['livewire-powergrid.filter' => 'outside']);
|
||||||
//權限設定
|
|
||||||
$this->canDownload=true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUp(): array
|
public function setUp(): array
|
||||||
{
|
{
|
||||||
if($this->canDownload ){
|
|
||||||
$this->showCheckBox();
|
|
||||||
}
|
|
||||||
$actions = [];
|
$actions = [];
|
||||||
if($this->canDownload){
|
|
||||||
$actions[]=PowerGrid::exportable(fileName: $this->tableName.'-file')
|
|
||||||
->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV);
|
|
||||||
}
|
|
||||||
$header = PowerGrid::header()
|
$header = PowerGrid::header()
|
||||||
->withoutLoading()
|
->withoutLoading()
|
||||||
->showToggleColumns();
|
->showToggleColumns();
|
||||||
//->showSoftDeletes()
|
|
||||||
//->showSearchInput()
|
|
||||||
$header->includeViewOnTop('livewire.admin.activity-log-header');
|
$header->includeViewOnTop('livewire.admin.activity-log-header');
|
||||||
|
|
||||||
$actions[]=$header;
|
$actions[]=$header;
|
||||||
|
96
app/Livewire/Admin/MachineStatusTable.php
Normal file
96
app/Livewire/Admin/MachineStatusTable.php
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Admin;
|
||||||
|
|
||||||
|
use App\Models\MachineStatus;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Button;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Column;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Traits\WithExport;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable;
|
||||||
|
|
||||||
|
final class MachineStatusTable extends PowerGridComponent
|
||||||
|
{
|
||||||
|
public string $tableName = 'machine-status-table';
|
||||||
|
public bool $canDownload;
|
||||||
|
|
||||||
|
public bool $showFilters = false;
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
config(['livewire-powergrid.filter' => 'outside']);
|
||||||
|
//權限設定
|
||||||
|
$this->canDownload=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp(): array
|
||||||
|
{
|
||||||
|
if($this->canDownload ){
|
||||||
|
$this->showCheckBox();
|
||||||
|
}
|
||||||
|
$actions = [];
|
||||||
|
if($this->canDownload){
|
||||||
|
$actions[]=PowerGrid::exportable(fileName: $this->tableName.'-file')
|
||||||
|
->type(Exportable::TYPE_XLS, Exportable::TYPE_CSV);
|
||||||
|
}
|
||||||
|
$header = PowerGrid::header()
|
||||||
|
->withoutLoading()
|
||||||
|
->showToggleColumns();
|
||||||
|
|
||||||
|
$header->includeViewOnTop('livewire.admin.machine-status-header');
|
||||||
|
|
||||||
|
$actions[]=$header;
|
||||||
|
$actions[]=PowerGrid::footer()->showPerPage()->showRecordCount();
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function datasource(): Builder
|
||||||
|
{
|
||||||
|
return MachineStatus::query()->latest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function relationSearch(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fields(): PowerGridFields
|
||||||
|
{
|
||||||
|
return PowerGrid::fields()
|
||||||
|
->add('id')
|
||||||
|
->add('hostname')
|
||||||
|
->add('ip')
|
||||||
|
->add('cpu')
|
||||||
|
->add('memory')
|
||||||
|
->add('disk')
|
||||||
|
->add('created_at');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columns(): array
|
||||||
|
{
|
||||||
|
$column=[];
|
||||||
|
$column[]=Column::make('Id', 'id');
|
||||||
|
$column[]=Column::make(__('machine-status.hostname'), 'hostname')->sortable()->searchable();
|
||||||
|
$column[]=Column::make(__('machine-status.Ip'), 'ip')->sortable()->searchable();
|
||||||
|
$column[]=Column::make(__('machine-status.Cpu'), 'cpu')->sortable()->searchable();
|
||||||
|
$column[]=Column::make(__('machine-status.Memory'), 'memory')->sortable()->searchable();
|
||||||
|
$column[]=Column::make(__('machine-status.Disk'), 'disk')->sortable()->searchable();
|
||||||
|
$column[]=Column::make(__('machine-status.Created at'), 'created_at')->sortable()->searchable();
|
||||||
|
|
||||||
|
return $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filters(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Filter::datetimepicker('created_at'),
|
||||||
|
Filter::inputText('hostname')->placeholder(__('machine-status.hostname')),
|
||||||
|
Filter::inputText('ip')->placeholder(__('machine-status.Ip')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
82
app/Livewire/Admin/RoomStatusLogTable.php
Normal file
82
app/Livewire/Admin/RoomStatusLogTable.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Admin;
|
||||||
|
|
||||||
|
use App\Models\RoomStatusLog;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Button;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Column;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||||
|
|
||||||
|
final class RoomStatusLogTable extends PowerGridComponent
|
||||||
|
{
|
||||||
|
public string $tableName = 'room-status-log-table';
|
||||||
|
|
||||||
|
public bool $showFilters = false;
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
config(['livewire-powergrid.filter' => 'outside']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp(): array
|
||||||
|
{
|
||||||
|
$actions = [];
|
||||||
|
$header = PowerGrid::header()
|
||||||
|
->withoutLoading()
|
||||||
|
->showToggleColumns();
|
||||||
|
$header->includeViewOnTop('livewire.admin.room-status-log-header');
|
||||||
|
|
||||||
|
$actions[]=$header;
|
||||||
|
$actions[]=PowerGrid::footer()->showPerPage()->showRecordCount();
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function datasource(): Builder
|
||||||
|
{
|
||||||
|
return RoomStatusLog::query()->latest();;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function relationSearch(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fields(): PowerGridFields
|
||||||
|
{
|
||||||
|
return PowerGrid::fields()
|
||||||
|
->add('id')
|
||||||
|
->add('room_name', function (RoomStatusLog $model) {
|
||||||
|
return $model->room?->type->labelPowergridFilter().$model->room?->name;
|
||||||
|
})
|
||||||
|
->add('user_name', function (RoomStatusLog $model){
|
||||||
|
return $model->user?->name;
|
||||||
|
})
|
||||||
|
->add('status_str',function (RoomStatusLog $model){
|
||||||
|
return $model->status->labelPowergridFilter();
|
||||||
|
})
|
||||||
|
->add('message')
|
||||||
|
->add('created_at');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columns(): array
|
||||||
|
{
|
||||||
|
$column=[];
|
||||||
|
$column[]=Column::make('Id', 'id');
|
||||||
|
$column[]=Column::make('Room', 'room_name');
|
||||||
|
$column[]=Column::make('User', 'user_name');
|
||||||
|
$column[]=Column::make('Status', 'status_str');
|
||||||
|
$column[]=Column::make('Message', 'message');
|
||||||
|
$column[]=Column::make('Created at', 'created_at');
|
||||||
|
return $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filters(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
135
app/Livewire/Admin/RoomTable.php
Normal file
135
app/Livewire/Admin/RoomTable.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Admin;
|
||||||
|
|
||||||
|
use App\Models\Room;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Button;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Column;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||||
|
|
||||||
|
final class RoomTable extends PowerGridComponent
|
||||||
|
{
|
||||||
|
public string $tableName = 'room-table';
|
||||||
|
|
||||||
|
public bool $showFilters = false;
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
config(['livewire-powergrid.filter' => 'outside']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp(): array
|
||||||
|
{
|
||||||
|
$actions = [];
|
||||||
|
$header = PowerGrid::header()
|
||||||
|
->withoutLoading()
|
||||||
|
->showToggleColumns();
|
||||||
|
$header->includeViewOnTop('livewire.admin.room-header');
|
||||||
|
|
||||||
|
$actions[]=$header;
|
||||||
|
$actions[]=PowerGrid::footer()->showPerPage()->showRecordCount();
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function datasource(): Builder
|
||||||
|
{
|
||||||
|
return Room::query();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function relationSearch(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fields(): PowerGridFields
|
||||||
|
{
|
||||||
|
return PowerGrid::fields()
|
||||||
|
->add('id')
|
||||||
|
->add('floor')
|
||||||
|
->add('room_name',function (Room $model){
|
||||||
|
return $model->type->labelPowergridFilter().$model->name;
|
||||||
|
})
|
||||||
|
->add('is_online')
|
||||||
|
->add('status_str',function (Room $model){
|
||||||
|
return $model->status->labelPowergridFilter();
|
||||||
|
})
|
||||||
|
->add('started_at_formatted', fn (Room $model) => Carbon::parse($model->started_at)->format('Y/m/d H:i:s'))
|
||||||
|
->add('ended_at_formatted', fn (Room $model) => Carbon::parse($model->ended_at)->format('Y/m/d H:i:s'))
|
||||||
|
->add('created_at');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columns(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Column::make('Id', 'id'),
|
||||||
|
Column::make('Floor', 'floor')
|
||||||
|
->sortable()
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::make('Name', 'room_name')
|
||||||
|
->sortable()
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::make('Is online', 'is_online')
|
||||||
|
->sortable()
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::make('Status', 'status_str')
|
||||||
|
->sortable()
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::make('Started at', 'started_at_formatted', 'started_at')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
|
Column::make('Ended at', 'ended_at_formatted', 'ended_at')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
|
Column::make('Created at', 'created_at')
|
||||||
|
->sortable()
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::action('Action')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filters(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Filter::datetimepicker('started_at'),
|
||||||
|
Filter::datetimepicker('ended_at'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[\Livewire\Attributes\On('edit')]
|
||||||
|
public function edit($rowId): void
|
||||||
|
{
|
||||||
|
$this->js('alert('.$rowId.')');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function actions(Room $row): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Button::add('edit')
|
||||||
|
->slot('Edit: '.$row->id)
|
||||||
|
->id()
|
||||||
|
->class('pg-btn-white dark:ring-pg-primary-600 dark:border-pg-primary-600 dark:hover:bg-pg-primary-700 dark:ring-offset-pg-primary-800 dark:text-pg-primary-300 dark:bg-pg-primary-700')
|
||||||
|
->dispatch('edit', ['rowId' => $row->id])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public function actionRules($row): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// Hide button edit for ID 1
|
||||||
|
Rule::button('edit')
|
||||||
|
->when(fn($row) => $row->id === 1)
|
||||||
|
->hide(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
121
app/Livewire/Admin/SongLibraryCacheTable.php
Normal file
121
app/Livewire/Admin/SongLibraryCacheTable.php
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Admin;
|
||||||
|
|
||||||
|
use App\Models\SongLibraryCache;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Button;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Column;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\Filter;
|
||||||
|
use PowerComponents\LivewirePowerGrid\Facades\PowerGrid;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridFields;
|
||||||
|
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
|
||||||
|
|
||||||
|
final class SongLibraryCacheTable extends PowerGridComponent
|
||||||
|
{
|
||||||
|
public string $tableName = 'song-library-cache-table';
|
||||||
|
public string $primaryKey = 'song_id';
|
||||||
|
public string $sortField = 'song_id';
|
||||||
|
public bool $useQueryBuilderPagination = true;
|
||||||
|
|
||||||
|
public bool $canDownload;
|
||||||
|
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
config(['livewire-powergrid.filter' => 'outside']);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUp(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
$actions = [];
|
||||||
|
|
||||||
|
$header = PowerGrid::header()
|
||||||
|
->withoutLoading()
|
||||||
|
->showToggleColumns();
|
||||||
|
|
||||||
|
$header->includeViewOnTop('livewire.admin.song-library-cache-header');
|
||||||
|
|
||||||
|
$actions[]=$header;
|
||||||
|
$actions[]=PowerGrid::footer()->showPerPage()->showRecordCount();
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function datasource(): Builder
|
||||||
|
{
|
||||||
|
return SongLibraryCache::query()->orderBy('song_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function relationSearch(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fields(): PowerGridFields
|
||||||
|
{
|
||||||
|
return PowerGrid::fields()
|
||||||
|
->add('song_id')
|
||||||
|
->add('song_name')
|
||||||
|
->add('song_simplified')
|
||||||
|
->add('phonetic_abbr')
|
||||||
|
->add('pinyin_abbr')
|
||||||
|
->add('strokes_abbr')
|
||||||
|
->add('song_number')
|
||||||
|
->add('artistA')
|
||||||
|
->add('artistB')
|
||||||
|
->add('artistA_simplified')
|
||||||
|
->add('artistB_simplified')
|
||||||
|
->add('artistA_category')
|
||||||
|
->add('artistB_category')
|
||||||
|
->add('artist_category')
|
||||||
|
->add('song_filename')
|
||||||
|
->add('song_category')
|
||||||
|
->add('language_name')
|
||||||
|
->add('add_date_formatted', fn (SongLibraryCache $model) => Carbon::parse($model->add_date)->format('d/m/Y'))
|
||||||
|
->add('situation')
|
||||||
|
->add('vocal')
|
||||||
|
->add('db_change')
|
||||||
|
->add('song_counts')
|
||||||
|
->add('updated_at_formatted', fn (SongLibraryCache $model) => Carbon::parse($model->updated_at)->format('d/m/Y H:i:s'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function columns(): array
|
||||||
|
{
|
||||||
|
$column=[];
|
||||||
|
$column[]=Column::make('Song id', 'song_id');
|
||||||
|
$column[]=Column::make('Song name', 'song_name')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Song simplified', 'song_simplified')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Phonetic abbr', 'phonetic_abbr')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Pinyin abbr', 'pinyin_abbr')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Strokes abbr', 'strokes_abbr')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Song number', 'song_number')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('ArtistA', 'artistA')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('ArtistB', 'artistB')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('ArtistA simplified', 'artistA_simplified')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('ArtistB simplified', 'artistB_simplified')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('ArtistA category', 'artistA_category')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('ArtistB category', 'artistB_category')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Artist category', 'artist_category')->sortable()->searchable()->hidden(true, false);
|
||||||
|
$column[]=Column::make('Song filename', 'song_filename')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Song category', 'song_category')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Language name', 'language_name')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Add date', 'add_date_formatted', 'add_date')->sortable();
|
||||||
|
$column[]=Column::make('Situation', 'situation')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Vocal', 'vocal')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Db change', 'db_change')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Song counts', 'song_counts')->sortable()->searchable();
|
||||||
|
$column[]=Column::make('Updated at', 'updated_at_formatted', 'updated_at')->sortable()->hidden(true, false);
|
||||||
|
return $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filters(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Filter::datepicker('add_date'),
|
||||||
|
Filter::datetimepicker('updated_at'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,4 +28,30 @@ class MachineStatus extends Model
|
|||||||
'disk',
|
'disk',
|
||||||
'status',
|
'status',
|
||||||
];
|
];
|
||||||
|
public function save(array $options = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("MachineStatus is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
throw new \Exception("MachineStatus cannot be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function create(array $attributes = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("MachineStatus is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function booted()
|
||||||
|
{
|
||||||
|
// 防止 mass update/delete
|
||||||
|
static::updating(function () {
|
||||||
|
throw new \Exception("Updating is not allowed.");
|
||||||
|
});
|
||||||
|
|
||||||
|
static::deleting(function () {
|
||||||
|
throw new \Exception("Deleting is not allowed.");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
|
|
||||||
class RoomStatusLog extends Model
|
class RoomStatusLog extends Model
|
||||||
{
|
{
|
||||||
/** @use HasFactory<\Database\Factories\ArtistFactory> */
|
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
@ -23,8 +22,36 @@ class RoomStatusLog extends Model
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'status' => \App\Enums\RoomStatus::class,
|
'status' => \App\Enums\RoomStatus::class,
|
||||||
];
|
];
|
||||||
|
public function user(){
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
public function room() {
|
public function room() {
|
||||||
return $this->belongsTo(Room::class);
|
return $this->belongsTo(Room::class);
|
||||||
}
|
}
|
||||||
|
public function save(array $options = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("RoomStatusLog is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
throw new \Exception("RoomStatusLog cannot be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function create(array $attributes = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("RoomStatusLog is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function booted()
|
||||||
|
{
|
||||||
|
// 防止 mass update/delete
|
||||||
|
static::updating(function () {
|
||||||
|
throw new \Exception("Updating is not allowed.");
|
||||||
|
});
|
||||||
|
|
||||||
|
static::deleting(function () {
|
||||||
|
throw new \Exception("Deleting is not allowed.");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
67
app/Models/SongLibraryCache.php
Normal file
67
app/Models/SongLibraryCache.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class SongLibraryCache extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'song_library_cache';
|
||||||
|
protected $primaryKey = 'song_id';
|
||||||
|
public $incrementing = true;
|
||||||
|
protected $keyType = 'int';
|
||||||
|
const CREATED_AT = null;
|
||||||
|
const UPDATED_AT = 'updated_at';
|
||||||
|
|
||||||
|
// 可寫入的欄位(可依需要擴充)
|
||||||
|
protected $fillable = [
|
||||||
|
'song_name',
|
||||||
|
'song_simplified',
|
||||||
|
'phonetic_abbr',
|
||||||
|
'pinyin_abbr',
|
||||||
|
'strokes_abbr',
|
||||||
|
'song_number',
|
||||||
|
'artistA',
|
||||||
|
'artistB',
|
||||||
|
'artistA_simplified',
|
||||||
|
'artistB_simplified',
|
||||||
|
'artistA_category',
|
||||||
|
'artistB_category',
|
||||||
|
'artist_category',
|
||||||
|
'song_filename',
|
||||||
|
'song_category',
|
||||||
|
'language_name',
|
||||||
|
'add_date',
|
||||||
|
'situation',
|
||||||
|
'vocal',
|
||||||
|
'db_change',
|
||||||
|
'song_counts',
|
||||||
|
'updated_at',
|
||||||
|
];
|
||||||
|
public function save(array $options = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("SongLibraryCache is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
throw new \Exception("SongLibraryCache cannot be deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function create(array $attributes = [])
|
||||||
|
{
|
||||||
|
throw new \Exception("SongLibraryCache is read-only.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function booted()
|
||||||
|
{
|
||||||
|
// 防止 mass update/delete
|
||||||
|
static::updating(function () {
|
||||||
|
throw new \Exception("Updating is not allowed.");
|
||||||
|
});
|
||||||
|
|
||||||
|
static::deleting(function () {
|
||||||
|
throw new \Exception("Deleting is not allowed.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
11
resources/lang/zh-tw/machine-status.php
Normal file
11
resources/lang/zh-tw/machine-status.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'list' => '設備紀錄',
|
||||||
|
'hostname' => '設備名稱',
|
||||||
|
'Ip' => 'IP',
|
||||||
|
'Cpu' => 'CPU',
|
||||||
|
'Memory'=>'記憶體',
|
||||||
|
'Disk' =>'硬碟',
|
||||||
|
'Created at' => '建立於'
|
||||||
|
];
|
7
resources/lang/zh-tw/room.php
Normal file
7
resources/lang/zh-tw/room.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'active' => '正常',
|
||||||
|
'error' => '維修',
|
||||||
|
|
||||||
|
];
|
@ -1,12 +1,3 @@
|
|||||||
@php
|
|
||||||
use App\Enums\RoomStatus;
|
|
||||||
$statusColors = [
|
|
||||||
RoomStatus::Active->value => 'green-600',
|
|
||||||
RoomStatus::Closed->value => 'gray-600',
|
|
||||||
RoomStatus::Error->value => 'red-600',
|
|
||||||
];
|
|
||||||
@endphp
|
|
||||||
|
|
||||||
<div class="border p-2 rounded shadow-md h-32 relative cursor-pointer bg-amber-50">
|
<div class="border p-2 rounded shadow-md h-32 relative cursor-pointer bg-amber-50">
|
||||||
{{-- 房間名稱 + 線上狀態圓點 --}}
|
{{-- 房間名稱 + 線上狀態圓點 --}}
|
||||||
<div class="font-bold flex items-center gap-1">
|
<div class="font-bold flex items-center gap-1">
|
||||||
@ -16,7 +7,7 @@
|
|||||||
<span>{{ $room->type->labels().".".$room->name }}</span>
|
<span>{{ $room->type->labels().".".$room->name }}</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-{{ $statusColors[$room->status->value] ?? 'gray-500' }} text-center">
|
<div class="text-sm text-{{ $room->is_online ? 'green-600': 'red-600' }} text-center">
|
||||||
{{ $room->status->labels() }}
|
{{ $room->is_online ? __('room.active') : __('room.error') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -17,10 +17,16 @@
|
|||||||
<span>{{ $room->type->labels().".".$room->name }}</span>
|
<span>{{ $room->type->labels().".".$room->name }}</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@if(!$room->is_online)
|
||||||
|
<div class="text-sm text-red-600 text-center">
|
||||||
|
{{ __('room.error') }}
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
<div class="text-sm text-{{ $statusColors[$room->status->value] ?? 'gray-500' }} text-center">
|
<div class="text-sm text-{{ $statusColors[$room->status->value] ?? 'gray-500' }} text-center">
|
||||||
{{ $room->status->labels() }}
|
{{ $room->status->labels() }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-center whitespace-nowrap ">{{ $room->str_started_at() }}</div>
|
<div class="text-xs text-center whitespace-nowrap ">{{ $room->str_started_at() }}</div>
|
||||||
<div class="text-xs text-center whitespace-nowrap ">{{ $room->str_ended_at() }}</div>
|
<div class="text-xs text-center whitespace-nowrap ">{{ $room->str_ended_at() }}</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
<x-layouts.admin>
|
<x-layouts.admin>
|
||||||
<livewire:admin.branch-table />
|
|
||||||
|
<livewire:admin.room-table/>
|
||||||
</x-layouts.admin>
|
</x-layouts.admin>
|
@ -0,0 +1,2 @@
|
|||||||
|
<x-admin.section-header title="{{ __('machine-status.list') }}">
|
||||||
|
</x-admin.section-header>
|
3
resources/views/livewire/admin/machine-status.blade.php
Normal file
3
resources/views/livewire/admin/machine-status.blade.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<x-layouts.admin>
|
||||||
|
<livewire:admin.machine-status-table />
|
||||||
|
</x-layouts.admin>
|
2
resources/views/livewire/admin/room-header.blade.php
Normal file
2
resources/views/livewire/admin/room-header.blade.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<x-admin.section-header title="{{ __('room.list') }}">
|
||||||
|
</x-admin.section-header>
|
@ -0,0 +1,2 @@
|
|||||||
|
<x-admin.section-header title="{{ __('room-status-log.list') }}">
|
||||||
|
</x-admin.section-header>
|
3
resources/views/livewire/admin/room-status-log.blade.php
Normal file
3
resources/views/livewire/admin/room-status-log.blade.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<x-layouts.admin>
|
||||||
|
<livewire:admin.room-status-log-table />
|
||||||
|
</x-layouts.admin>
|
@ -0,0 +1,2 @@
|
|||||||
|
<x-admin.section-header title="{{ __('song-library-cache.list') }}">
|
||||||
|
</x-admin.section-header>
|
@ -0,0 +1,3 @@
|
|||||||
|
<x-layouts.admin>
|
||||||
|
<livewire:admin.song-library-cache-table />
|
||||||
|
</x-layouts.admin>
|
@ -7,7 +7,10 @@ new class extends Component
|
|||||||
{
|
{
|
||||||
public array $menus=[
|
public array $menus=[
|
||||||
['label' => 'Dashboard', 'route' => 'admin.dashboard', 'icon' => 'home', 'permission' => null],
|
['label' => 'Dashboard', 'route' => 'admin.dashboard', 'icon' => 'home', 'permission' => null],
|
||||||
|
['label' => 'Song', 'route' => 'admin.song-library-cache', 'icon' => 'clock', 'permission' => null],
|
||||||
['label' => 'ActivityLog', 'route' => 'admin.activity-log', 'icon' => 'clock', 'permission' => null],
|
['label' => 'ActivityLog', 'route' => 'admin.activity-log', 'icon' => 'clock', 'permission' => null],
|
||||||
|
['label' => 'RoomStatusLog', 'route' => 'admin.room-status-log', 'icon' => 'clock', 'permission' => null],
|
||||||
|
['label' => 'MachineStatus', 'route' => 'admin.machine-status', 'icon' => 'clock', 'permission' => null],
|
||||||
['label' => 'User', 'route' => 'admin.users', 'icon' => 'user-circle', 'permission' => 'user-list'],
|
['label' => 'User', 'route' => 'admin.users', 'icon' => 'user-circle', 'permission' => 'user-list'],
|
||||||
['label' => 'Branche', 'route' => 'admin.branches', 'icon' => 'building-library', 'permission' => 'room-list'],
|
['label' => 'Branche', 'route' => 'admin.branches', 'icon' => 'building-library', 'permission' => 'room-list'],
|
||||||
['label' => 'Room', 'route' => 'admin.rooms', 'icon' => 'film', 'permission' => 'room-list'],
|
['label' => 'Room', 'route' => 'admin.rooms', 'icon' => 'film', 'permission' => 'room-list'],
|
||||||
|
@ -20,7 +20,10 @@ require __DIR__.'/auth.php';
|
|||||||
|
|
||||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||||
Route::get('/dashboard', AdminDashboard::class)->name('dashboard');
|
Route::get('/dashboard', AdminDashboard::class)->name('dashboard');
|
||||||
|
Route::get('/song-library-cache', function () {return view('livewire.admin.song-library-cache');})->name('song-library-cache');
|
||||||
Route::get('/activity-log', function () {return view('livewire.admin.activity-log');})->name('activity-log');
|
Route::get('/activity-log', function () {return view('livewire.admin.activity-log');})->name('activity-log');
|
||||||
|
Route::get('/room-status-log', function () {return view('livewire.admin.room-status-log');})->name('room-status-log');
|
||||||
|
Route::get('/machine-status', function () {return view('livewire.admin.machine-status');})->name('machine-status');
|
||||||
Route::get('/users', function () {return view('livewire.admin.users');})->name('users');
|
Route::get('/users', function () {return view('livewire.admin.users');})->name('users');
|
||||||
Route::get('/branches', function () {return view('livewire.admin.branches');})->name('branches');
|
Route::get('/branches', function () {return view('livewire.admin.branches');})->name('branches');
|
||||||
Route::get('/rooms', function () {return view('livewire.admin.rooms');})->name('rooms');
|
Route::get('/rooms', function () {return view('livewire.admin.rooms');})->name('rooms');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user