From 42f69e677aaaff0e7e0ee09fc9fbf81ec66da028 Mon Sep 17 00:00:00 2001 From: "allen.yan" Date: Thu, 28 Aug 2025 17:22:49 +0800 Subject: [PATCH] =?UTF-8?q?202508281721=20=E5=8A=A0=E5=85=A5=20=E5=B7=B1?= =?UTF-8?q?=E9=BB=9E=E6=AD=8C=E6=9B=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Enums/OrderedSongStatus.php | 28 ++++++ app/Livewire/Layout/Navigation.php | 2 - app/Livewire/Pages/OrderedSongList.php | 58 ++++++++++++ app/Models/OrderedSong.php | 83 +++++++++++++++++ app/Models/RoomSession.php | 42 +++++++++ resources/views/clicked-song.blade.php | 10 +++ .../pages/ordered-song-list.blade.php | 88 +++++++++++++++++++ routes/web.php | 1 + 8 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 app/Enums/OrderedSongStatus.php create mode 100644 app/Livewire/Pages/OrderedSongList.php create mode 100644 app/Models/OrderedSong.php create mode 100644 app/Models/RoomSession.php create mode 100644 resources/views/clicked-song.blade.php create mode 100644 resources/views/livewire/pages/ordered-song-list.blade.php diff --git a/app/Enums/OrderedSongStatus.php b/app/Enums/OrderedSongStatus.php new file mode 100644 index 0000000..1b65a2e --- /dev/null +++ b/app/Enums/OrderedSongStatus.php @@ -0,0 +1,28 @@ + __('enums.NotPlayed'), + self::Playing => __('enums.Playing'), + self::Played => __('enums.Played'), + self::NoFile => __('enums.NoFile'), + self::Skipped => __('enums.Skipped'), + self::InsertPlayback => __('enums.InsertPlayback'), + }; + } +} \ No newline at end of file diff --git a/app/Livewire/Layout/Navigation.php b/app/Livewire/Layout/Navigation.php index 6736a5b..40f651f 100644 --- a/app/Livewire/Layout/Navigation.php +++ b/app/Livewire/Layout/Navigation.php @@ -16,9 +16,7 @@ class Navigation extends Component private array $roomMenus = [ ['name' => '已點歌曲', 'route' => 'clicked-song'], ['name' => '聲音控制', 'route' => 'sound-control'], - ['name' => '社群媒體', 'route' => 'social-media'], ['name' => '真情告白', 'route' => 'love-message'], - ['name' => '心情貼圖', 'route' => 'mood-stickers'], ]; public array $menus = []; diff --git a/app/Livewire/Pages/OrderedSongList.php b/app/Livewire/Pages/OrderedSongList.php new file mode 100644 index 0000000..ccaba3b --- /dev/null +++ b/app/Livewire/Pages/OrderedSongList.php @@ -0,0 +1,58 @@ +playing = new EloquentCollection(); + $this->nextSong = new EloquentCollection(); + $this->finished = new EloquentCollection(); + $roomSession = $this->getRoomSession(session('room_code'))?->id ; + if ($roomSession) { + $this->roomSessionId = $roomSession->id; + $this->loadSongs($this->roomSessionId); + } + } + private function getRoomSession($api_token): ?RoomSession + { + if (!$apiToken) return null; + return RoomSession::where('api_token', $api_token) + ->whereIn('status', ['active', 'maintain']) + ->first(); + } + + public function refreshSongs() + { + if ($this->roomSessionId) { + $this->loadSongs($this->roomSessionId); + } + } + protected function loadSongs(string $roomSessionId) + { + $this->playing = OrderedSong::forSession($roomSessionId)->playing()->get(); + $this->nextSong = OrderedSong::forSession($roomSessionId)->nextSong()->get(); + $this->finished = OrderedSong::forSession($roomSessionId)->finished()->get(); + } + public function render() + { + return view('livewire.pages.ordered-song-list', [ + 'playing' => $this->playing, + 'nextSong' => $this->nextSong, + 'finished' => $this->finished, + ]); + } +} diff --git a/app/Models/OrderedSong.php b/app/Models/OrderedSong.php new file mode 100644 index 0000000..38f2cc4 --- /dev/null +++ b/app/Models/OrderedSong.php @@ -0,0 +1,83 @@ + 'datetime', + 'started_at' => 'datetime', + 'finished_at' => 'datetime', + 'status' => \App\Enums\OrderedSongStatus::class, + ]; + + + public function session() + { + return $this->belongsTo(RoomSession::class, 'room_session_id'); + } + + public function song() + { + return $this->belongsTo(Song::class); + } + public function scopeWithPartialSong($query) + { + return $query->with([ + 'song' => function ($q) { + $q->select('id', 'name','filename','db_change','vocal','situation'); // 精簡版 + } + ]); + } + public function scopeForSession($query, $roomSessionId) + { + return $query->where('room_session_id', $roomSessionId); + } + + public function scopePlaying($query) + { + return $query->where('status', OrderedSongStatus::Playing); + } + + public function scopeNextSong($query) + { + return $query->whereIn('status', [OrderedSongStatus::InsertPlayback, OrderedSongStatus::NotPlayed]) + ->orderByRaw("FIELD(status, ?, ?)", [ + OrderedSongStatus::InsertPlayback->value, + OrderedSongStatus::NotPlayed->value, + ]) + ->orderByRaw("CASE WHEN status=? THEN ordered_at END DESC", [OrderedSongStatus::InsertPlayback->value]) + ->orderByRaw("CASE WHEN status=? THEN ordered_at END ASC", [OrderedSongStatus::NotPlayed->value]); + } + + public function scopeFinished($query) + { + return $query->whereIn('status', [ + OrderedSongStatus::Played, + OrderedSongStatus::Skipped, + OrderedSongStatus::NoFile, + ])->orderByDesc('finished_at'); + } +} diff --git a/app/Models/RoomSession.php b/app/Models/RoomSession.php new file mode 100644 index 0000000..7b17096 --- /dev/null +++ b/app/Models/RoomSession.php @@ -0,0 +1,42 @@ + 'datetime', + 'ended_at' => 'datetime', + ]; + + // 狀態常數 + public const STATUS_ACTIVE = 'active'; + public const STATUS_CLOSED = 'closed'; + public const STATUS_FORCE_CLOSED = 'force_closed'; + public const STATUS_FIRE_CLOSED = 'fire_closed'; + + // 模式常數 + public const MODE_NORMAL = 'normal'; + public const MODE_VIP = 'vip'; + public const MODE_TEST = 'test'; + + public function room() + { + return $this->belongsTo(Room::class); + } +} diff --git a/resources/views/clicked-song.blade.php b/resources/views/clicked-song.blade.php new file mode 100644 index 0000000..ca8899e --- /dev/null +++ b/resources/views/clicked-song.blade.php @@ -0,0 +1,10 @@ + + +
超級巨星 自助式KTV
+ +
+ + +
\ No newline at end of file diff --git a/resources/views/livewire/pages/ordered-song-list.blade.php b/resources/views/livewire/pages/ordered-song-list.blade.php new file mode 100644 index 0000000..6a5d705 --- /dev/null +++ b/resources/views/livewire/pages/ordered-song-list.blade.php @@ -0,0 +1,88 @@ +
+ + + + + 編號 + 歌曲 + 狀態 + + + + {{-- 正在播放 --}} + + + 🎵 正在播放 + + + @forelse($playing as $song) + + {{ $song->song_id }} + +
+ {{ $song->song_name }} + {{ $song->artist_name }} +
+ + {{ $song->status->labels() }} + + @empty + + + 目前沒有正在播放的歌曲 + + + @endforelse + + {{-- 待播 / 插播 --}} + + + ⏳ 待播 / 插播 + + + @forelse($nextSong as $song) + + {{ $song->song_id }} + +
+ {{ $song->song_name }} + {{ $song->artist_name }} +
+ + {{ $song->status->labels() }} + + @empty + + + 目前沒有待播歌曲 + + + @endforelse + + {{-- 已結束播放 --}} + + + ✅ 已結束播放 + + + @forelse($finished as $song) + + {{ $song->song_id }} + +
+ {{ $song->song_name }} + {{ $song->artist_name }} +
+ + {{ $song->status->labels() }} + + @empty + + + 尚無結束播放的歌曲 + + + @endforelse + +
+
\ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 7813cb2..079ba79 100644 --- a/routes/web.php +++ b/routes/web.php @@ -7,6 +7,7 @@ Route::view('/welcome', 'welcome')->name('welcome'); Route::view('/new-songs', 'new-songs')->name('new-songs'); Route::view('/top-ranking', 'top-ranking')->name('top-ranking'); Route::view('/search-song', 'search-song')->name('search-song'); +Route::view('/clicked-song', 'clicked-song')->name('clicked-song'); Route::view('/sound-control', 'sound-control')->name('sound-control'); Route::view('/love-message', 'love-message')->name('love-message');