202508271416

加入歌手查詢
This commit is contained in:
allen.yan 2025-08-27 14:17:55 +08:00
parent 55666c1475
commit 01ff6d46db
4 changed files with 75 additions and 22 deletions

View File

@ -12,7 +12,6 @@ class Navigation extends Component
['name' => '首頁', 'route' => 'welcome'], ['name' => '首頁', 'route' => 'welcome'],
['name' => '新歌快報', 'route' => 'new-songs'], ['name' => '新歌快報', 'route' => 'new-songs'],
['name' => '熱門排行', 'route' => 'top-ranking'], ['name' => '熱門排行', 'route' => 'top-ranking'],
['name' => '歌星查詢', 'route' => 'search-singer'],
['name' => '歌名查詢', 'route' => 'search-song'], ['name' => '歌名查詢', 'route' => 'search-song'],
['name' => '已點歌曲', 'route' => 'clicked-song'], ['name' => '已點歌曲', 'route' => 'clicked-song'],
['name' => '聲音控制', 'route' => 'sound-control'], ['name' => '聲音控制', 'route' => 'sound-control'],

View File

@ -3,6 +3,7 @@
namespace App\Livewire\Pages; namespace App\Livewire\Pages;
use Livewire\Component; use Livewire\Component;
use App\Models\Artist;
use App\Models\Song; use App\Models\Song;
class SearchSong extends Component class SearchSong extends Component
@ -10,6 +11,9 @@ class SearchSong extends Component
public string $search = ''; public string $search = '';
public $searchCategory = ''; public $searchCategory = '';
public $selectedLanguage = '國語'; // 預設語言 public $selectedLanguage = '國語'; // 預設語言
public $selectedArtists = []; // 儲存已選的歌手 id
public $artistOptions = []; // API 回傳的搜尋結果
public string $artistSearch = ''; // 即時搜尋文字
/** /**
* 初始化(接收外部傳入的分類參數) * 初始化(接收外部傳入的分類參數)
@ -26,10 +30,35 @@ class SearchSong extends Component
{ {
$this->selectedLanguage = $lang; $this->selectedLanguage = $lang;
} }
//public function updatedSearch() /**
//{ * 搜尋歌手(透過 API
// dd($this->search); */
//} public function updatedArtistSearch()
{
$search = $this->artistSearch;
if ($search) {
// 即時搜尋歌手,從資料庫查詢
$this->artistOptions = \App\Models\Artist::query()
->where('name', 'like', "{$search}%")
->limit(100)
->get(['id', 'name'])
->toArray();
} else {
$this->artistOptions = [];
}
}
public function addArtist($id, $name)
{
$this->selectedArtists[$id] = $name;
$this->artistSearch = ''; // 清空搜尋框
$this->artistOptions = [];
}
public function removeArtist($id)
{
unset($this->selectedArtists[$id]);
}
/** /**
* 點歌 * 點歌
@ -50,21 +79,13 @@ class SearchSong extends Component
protected function loadSongs() protected function loadSongs()
{ {
return Song::query() return Song::query()
->when($this->search !== null && $this->search !== '', function ($q) { ->when($this->search, fn($q) => $q->where('name', 'like', "%{$this->search}%"))
$q->where('name', 'like', "{$this->search}%"); ->when($this->selectedLanguage, fn($q) => $q->where('language_type', $this->selectedLanguage))
}) ->when($this->selectedArtists, fn ($q) => $q->whereHas('artists', fn ($q2) => $q2->whereIn('id', array_keys($this->selectedArtists))))
->when($this->selectedLanguage, function ($q) { ->when($this->searchCategory === 'New', fn($q) => $q->orderByDesc('created_at'))
$q->where('language_type', $this->selectedLanguage); ->when($this->searchCategory === 'Hot', fn($q) => $q->orderByDesc('song_counts'), fn($q) => $q->orderByDesc('id'))
}) //->take($this->search || $this->artistSearch ? 100 : 1000)
->when($this->searchCategory === 'New', function ($q) { ->take(1000)
$q->orderByDesc('created_at');
})
->when($this->searchCategory === 'Hot', function ($q) {
$q->orderByDesc('song_counts');
}, function ($q) {
$q->orderBy('name');
})
->take($this->search ? 100 : 200) // 搜尋就多拿點,不搜尋就少拿
->get(); ->get();
} }

View File

@ -1,5 +1,39 @@
<div class="space-y-4 p-4"> <div class="space-y-4 p-4">
<div class="space-y-2">
<input
type="text"
wire:model.live.debounce.250ms="artistSearch"
placeholder="搜尋歌手..."
class="border rounded-lg p-2 w-full focus:ring-2 focus:ring-pink-400 focus:outline-none"
/>
<!-- 搜尋結果清單 -->
@if(!empty($artistOptions))
<div class="border rounded max-h-40 overflow-y-auto bg-white shadow">
@foreach($artistOptions as $artist)
<div class="px-2 py-1 cursor-pointer hover:bg-pink-100 flex justify-between items-center"
wire:click="addArtist({{ $artist['id'] }}, '{{ $artist['name'] }}')">
{{ $artist['name'] }}
@if(in_array($artist['id'], $selectedArtists))
<span class="text-pink-500 font-bold"></span>
@endif
</div>
@endforeach
</div>
@endif
<!-- 已選歌手 -->
@if($selectedArtists)
<div class="flex gap-2 flex-wrap mt-2">
@foreach($selectedArtists as $artistId => $artistName)
<span class="bg-pink-200 text-pink-700 px-2 py-1 rounded-full flex items-center gap-1">
{{ $artistName }}
<button type="button" wire:click="removeArtist({{ $artistId }})" class="font-bold">&times;</button>
</span>
@endforeach
</div>
@endif
</div>
{{-- 搜尋框 --}} {{-- 搜尋框 --}}
<div class="w-full mb-4"> <div class="w-full mb-4">
<input <input

View File

@ -10,7 +10,6 @@
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
<x-button.flat-card image="{{ asset('手機點歌/首頁-新歌快報.png') }}" href="{{ route('new-songs') }}" /> <x-button.flat-card image="{{ asset('手機點歌/首頁-新歌快報.png') }}" href="{{ route('new-songs') }}" />
<x-button.flat-card image="{{ asset('手機點歌/首頁-熱門排行.png') }}" href="{{ route('top-ranking') }}" /> <x-button.flat-card image="{{ asset('手機點歌/首頁-熱門排行.png') }}" href="{{ route('top-ranking') }}" />
<x-button.flat-card image="{{ asset('手機點歌/首頁-歌星查詢.png') }}" href="{{ route('search-singer') }}" />
<x-button.flat-card image="{{ asset('手機點歌/首頁-歌名查詢.png') }}" href="{{ route('search-song') }}" /> <x-button.flat-card image="{{ asset('手機點歌/首頁-歌名查詢.png') }}" href="{{ route('search-song') }}" />
<x-button.flat-card image="{{ asset('手機點歌/首頁-已點歌曲.png') }}" onclick="orderSongAndNavigate()" /> <x-button.flat-card image="{{ asset('手機點歌/首頁-已點歌曲.png') }}" onclick="orderSongAndNavigate()" />
<x-button.flat-card image="{{ asset('手機點歌/首頁-聲音控制.png') }}" href="{{ route('sound-control') }}" /> <x-button.flat-card image="{{ asset('手機點歌/首頁-聲音控制.png') }}" href="{{ route('sound-control') }}" />