歌曲列表 20250425
This commit is contained in:
parent
d7240465af
commit
cbc3fc9d34
@ -9,7 +9,7 @@ use App\Models\ArtistCategory;
|
||||
|
||||
class ArtistForm extends Component
|
||||
{
|
||||
protected $listeners = ['openCreateArtistModal','openEditArtistModal', 'deleteArtist','bulkDeleteArtist'];
|
||||
protected $listeners = ['openCreateArtistModal','openEditArtistModal', 'deleteArtist'];
|
||||
|
||||
public bool $showCreateModal = false;
|
||||
public ?int $artistId = null;
|
||||
@ -53,14 +53,14 @@ class ArtistForm extends Component
|
||||
'name' => $this->name,
|
||||
]);
|
||||
|
||||
session()->flash('message', '使用者已更新');
|
||||
session()->flash('message', '歌手已更新');
|
||||
} else {
|
||||
$role = Artist::create([
|
||||
'category_id' => $this->selectedCategory,
|
||||
'name' => $this->name,
|
||||
]);
|
||||
|
||||
session()->flash('message', '使用者已新增');
|
||||
session()->flash('message', '歌手已新增');
|
||||
}
|
||||
|
||||
$this->resetFields();
|
||||
@ -70,7 +70,7 @@ class ArtistForm extends Component
|
||||
public function deleteArtist($id)
|
||||
{
|
||||
Artist::findOrFail($id)->delete();
|
||||
session()->flash('message', '使用者已刪除');
|
||||
session()->flash('message', '歌手已刪除');
|
||||
}
|
||||
|
||||
public function resetFields()
|
||||
|
@ -4,8 +4,98 @@ namespace App\Livewire\Admin;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
use App\Models\Song;
|
||||
use App\Models\SongCategory;
|
||||
use App\Models\SongLanguage;
|
||||
|
||||
class SongForm extends Component
|
||||
{
|
||||
protected $listeners = ['openCreateSongModal','openEditSongModal', 'deleteSong'];
|
||||
|
||||
public bool $showCreateModal = false;
|
||||
|
||||
public $songCategories =[];
|
||||
public $songLanguage =[];
|
||||
public $selectedCategories=[];
|
||||
public $selectedArtists=[];
|
||||
|
||||
public ?int $songId = null;
|
||||
|
||||
public array $fields = [
|
||||
'id' =>'',
|
||||
'name' => '',
|
||||
'adddate' => '',
|
||||
'filename' => '',
|
||||
'language_type' => '',
|
||||
|
||||
'db_change' => '',
|
||||
'vocal' => '',
|
||||
'situation' => '',
|
||||
'copyright01' => '',
|
||||
'copyright02' => '',
|
||||
'note01' => '',
|
||||
'note02' => '',
|
||||
'note03' => '',
|
||||
'note04' => '',
|
||||
'enable' => true,
|
||||
];
|
||||
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required|string|max:255',
|
||||
|
||||
];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->songCategories = SongCategory::all();
|
||||
$this->songLanguage = SongLanguage::all();
|
||||
}
|
||||
|
||||
public function openCreateSongModal()
|
||||
{
|
||||
$this->resetFields();
|
||||
$this->showCreateModal = true;
|
||||
}
|
||||
|
||||
public function openEditSongModal($id)
|
||||
{
|
||||
$song = Song::findOrFail($id);
|
||||
$this->songId = $song->id;
|
||||
$this->fields = $song->only(array_keys($this->fields));
|
||||
$this->showCreateModal = true;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
if ($this->songId) {
|
||||
$song = Song::findOrFail($this->songId);
|
||||
$song->update($this->fields);
|
||||
session()->flash('message', '歌曲已更新');
|
||||
} else {
|
||||
Song::create($this->fields);
|
||||
session()->flash('message', '歌曲已新增');
|
||||
}
|
||||
|
||||
$this->resetFields();
|
||||
$this->showCreateModal = false;
|
||||
}
|
||||
|
||||
public function deleteSong($id)
|
||||
{
|
||||
Song::findOrFail($id)->delete();
|
||||
session()->flash('message', '歌曲已刪除');
|
||||
}
|
||||
|
||||
public function resetFields()
|
||||
{
|
||||
foreach ($this->fields as $key => $value) {
|
||||
$this->fields[$key] = is_bool($value) ? false : '';
|
||||
}
|
||||
$this->songId = null;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.admin.song-form');
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Livewire\Admin;
|
||||
|
||||
use App\Models\Song;
|
||||
use App\Models\SongLanguage;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use PowerComponents\LivewirePowerGrid\Button;
|
||||
@ -20,6 +21,10 @@ final class SongTable extends PowerGridComponent
|
||||
{
|
||||
public string $tableName = 'song-table';
|
||||
|
||||
/* public bool $deferLoading = true;
|
||||
|
||||
public string $loadingComponent = 'components.my-custom-loading'; */
|
||||
|
||||
public bool $showFilters = false;
|
||||
|
||||
public function boot(): void
|
||||
@ -57,7 +62,10 @@ final class SongTable extends PowerGridComponent
|
||||
|
||||
public function datasource(): Builder
|
||||
{
|
||||
return Song::query();
|
||||
return Song::query()->with([
|
||||
'language:id,name',
|
||||
'artists:id,name'
|
||||
]);
|
||||
}
|
||||
|
||||
public function relationSearch(): array
|
||||
@ -70,9 +78,14 @@ final class SongTable extends PowerGridComponent
|
||||
return PowerGrid::fields()
|
||||
->add('id')
|
||||
->add('name')
|
||||
->add('adddate_formatted', fn (Song $model) => Carbon::parse($model->adddate)->format('d/m/Y'))
|
||||
->add('simplified')
|
||||
->add('phonetic_abbr')
|
||||
->add('pinyin_abbr')
|
||||
->add('filename')
|
||||
->add('language_type')
|
||||
->add('adddate_formatted', fn (Song $model) => Carbon::parse($model->adddate)->format('Y-m-d'))
|
||||
->add('song_artists' ,fn(Song $model)=> $model->str_artists())
|
||||
->add('language_type', fn (Song $model) => optional($model->language)->name)
|
||||
->add('song_categories', fn(Song $model) => $model->str_categories())
|
||||
->add('db_change')
|
||||
->add('vocal')
|
||||
->add('situation')
|
||||
@ -82,12 +95,9 @@ final class SongTable extends PowerGridComponent
|
||||
->add('note02')
|
||||
->add('note03')
|
||||
->add('note04')
|
||||
->add('enable')
|
||||
->add('enable', fn ($item) => $item->enable ? '✅' : '❌')
|
||||
->add('unnamed_21')
|
||||
->add('simplified')
|
||||
->add('phonetic_abbr')
|
||||
->add('pinyin_abbr')
|
||||
->add('created_at_formatted', fn (Song $model) => Carbon::parse($model->created_at)->format('d/m/Y H:i:s'));
|
||||
->add('created_at_formatted', fn (Song $model) => Carbon::parse($model->created_at)->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
public function columns(): array
|
||||
@ -98,14 +108,32 @@ final class SongTable extends PowerGridComponent
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
Column::make(__('songs.adddate'), 'adddate_formatted', 'adddate')
|
||||
->sortable(),
|
||||
|
||||
Column::make(__('songs.simplified'), 'simplified')
|
||||
->sortable()
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
Column::make(__('songs.name.phinetic'), 'phonetic_abbr')
|
||||
->sortable()
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
Column::make(__('songs.name.pinyin'), 'pinyin_abbr')
|
||||
->sortable()
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
|
||||
Column::make(__('songs.filename'), 'filename')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
Column::make(__('songs.language_type'), 'language_type'),
|
||||
Column::make(__('songs.adddate'), 'adddate_formatted', 'adddate')
|
||||
->sortable(),
|
||||
//歌手
|
||||
Column::make(__('songs.artists'), 'song_artists'),
|
||||
Column::make(__('songs.language_type'),'language_type', 'language.name')
|
||||
->searchable(),
|
||||
//分類
|
||||
Column::make(__('songs.categorys'), 'song_categories'),
|
||||
//點播次數
|
||||
Column::make('Db change', 'db_change'),
|
||||
Column::make(__('songs.vocal'), 'vocal'),
|
||||
Column::make(__('songs.situation'), 'situation')
|
||||
@ -118,7 +146,8 @@ final class SongTable extends PowerGridComponent
|
||||
|
||||
Column::make(__('songs.copyright02'), 'copyright02')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
|
||||
Column::make(__('songs.note01'), 'note01')
|
||||
->sortable()
|
||||
@ -130,29 +159,19 @@ final class SongTable extends PowerGridComponent
|
||||
|
||||
Column::make(__('songs.note03'), 'note03')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
|
||||
Column::make(__('songs.note04'), 'note04')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
|
||||
Column::make(__('songs.enable'), 'enable'),
|
||||
Column::make('Unnamed 21', 'unnamed_21')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
Column::make(__('songs.simplified'), 'simplified')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
Column::make(__('songs.name.phinetic'), 'phonetic_abbr')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
Column::make(__('songs.name.pinyin'), 'pinyin_abbr')
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
->searchable()
|
||||
->hidden(true, false),
|
||||
Column::make('Created at', 'created_at_formatted', 'created_at')
|
||||
->sortable(),
|
||||
|
||||
@ -163,7 +182,22 @@ final class SongTable extends PowerGridComponent
|
||||
public function filters(): array
|
||||
{
|
||||
return [
|
||||
Filter::inputText('name')->placeholder(__('songs.name')),
|
||||
Filter::inputText('phonetic_abbr')->placeholder(__('songs.name.phinetic')),
|
||||
Filter::inputText('pinyin_abbr')->placeholder(__('songs.name.pinyin_abbr')),
|
||||
Filter::inputText('filename')->placeholder(__('songs.filename')),
|
||||
Filter::datepicker('adddate'),
|
||||
Filter::select('language_type', 'language_type')
|
||||
->dataSource(SongLanguage::all())
|
||||
->optionValue('id')
|
||||
->optionLabel('name'),
|
||||
Filter::inputText('copyright01')->placeholder(__('songs.copyright01')),
|
||||
Filter::inputText('copyright02')->placeholder(__('songs.copyright02')),
|
||||
Filter::inputText('note01')->placeholder(__('songs.note01')),
|
||||
Filter::inputText('note02')->placeholder(__('songs.note02')),
|
||||
Filter::inputText('note03')->placeholder(__('songs.note03')),
|
||||
Filter::inputText('note04')->placeholder(__('songs.note04')),
|
||||
Filter::boolean('enable')->label('✅', '❌'),
|
||||
Filter::datetimepicker('created_at'),
|
||||
];
|
||||
}
|
||||
|
@ -32,17 +32,21 @@ class Song extends Model
|
||||
'pinyin_abbr',
|
||||
];
|
||||
|
||||
|
||||
public function str_artists(){
|
||||
return $this->artists->pluck('name')->implode(', ');
|
||||
}
|
||||
public function artists(){
|
||||
return $this->belongsToMany(Artist::class);
|
||||
}
|
||||
|
||||
public function str_categories(){
|
||||
return $this->categories->pluck('name')->implode(', ');
|
||||
}
|
||||
public function categories(){
|
||||
return $this->belongsToMany(SongCategory::class);
|
||||
}
|
||||
|
||||
public function language(){
|
||||
return $this->belongsTo(SongLanguage::class, 'languageType', 'id');
|
||||
return $this->belongsTo(SongLanguage::class, 'language_type', 'id');
|
||||
}
|
||||
protected static function booted()
|
||||
{
|
||||
|
@ -1,3 +1,59 @@
|
||||
<div>
|
||||
{{-- Be like water. --}}
|
||||
</div>
|
||||
<x-wireui:modal-card title="{{ $songId ? '編輯歌曲' : '新增歌曲' }}" wire:model.defer="showCreateModal">
|
||||
|
||||
<form wire:submit.prevent="save">
|
||||
<x-wireui:toggle label="啟用" wire:model.defer="fields.enable" />
|
||||
<div class="grid grid-cols-3 gap-4 sm:grid-cols-3">
|
||||
<x-wireui:input label="歌曲編號" wire:model.defer="fields.id" required />
|
||||
<x-wireui:input label="歌曲名稱" wire:model.defer="fields.name" required />
|
||||
<x-wireui:input label="檔名" wire:model.defer="fields.filename" />
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-4 sm:grid-cols-3">
|
||||
<x-wireui:select
|
||||
label="歌手"
|
||||
wire:model.defer="selectedArtists"
|
||||
placeholder="輸入搜尋歌手"
|
||||
:async-data="route('api.artists.search')"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
multiselect
|
||||
hide-empty-message
|
||||
/>
|
||||
<x-wireui:input label="語言類型" wire:model.defer="fields.language_type" />
|
||||
<x-wireui:select
|
||||
label="分類"
|
||||
wire:model.defer="selectedCategories"
|
||||
:options="$songCategories->map(fn($c) => ['label' => $c->name, 'value' => $c->id])->toArray()"
|
||||
option-label="label"
|
||||
option-value="value"
|
||||
multiselect
|
||||
placeholder="選擇分類"
|
||||
/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-4 sm:grid-cols-3">
|
||||
<x-wireui:input label="配唱" wire:model.defer="fields.vocal" />
|
||||
<x-wireui:input label="情境" wire:model.defer="fields.situation" />
|
||||
<x-wireui:input label="資料庫更新" wire:model.defer="fields.db_change" />
|
||||
<x-wireui:input label="新增日期" wire:model.defer="fields.adddate" type="date" />
|
||||
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 sm:grid-cols-2">
|
||||
<x-wireui:input label="版權1" wire:model.defer="fields.copyright01" />
|
||||
<x-wireui:input label="版權2" wire:model.defer="fields.copyright02" />
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4 sm:grid-cols-4">
|
||||
<x-wireui:textarea label="備註1" wire:model.defer="fields.note01" />
|
||||
<x-wireui:textarea label="備註2" wire:model.defer="fields.note02" />
|
||||
<x-wireui:textarea label="備註3" wire:model.defer="fields.note03" />
|
||||
<x-wireui:textarea label="備註4" wire:model.defer="fields.note04" />
|
||||
</div>
|
||||
{{-- Footer --}}
|
||||
<x-slot name="footer">
|
||||
<div class="flex justify-between w-full">
|
||||
<x-wireui:button flat label="取消" @click="$wire.showCreateModal = false" />
|
||||
<x-wireui:button primary type="submit" label="儲存" />
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
</form>
|
||||
|
||||
</x-wireui:modal-card>
|
@ -19,6 +19,13 @@ Route::view('profile', 'profile')
|
||||
->name('profile');
|
||||
|
||||
require __DIR__.'/auth.php';
|
||||
Route::get('/api/artists/search', function (Request $request) {
|
||||
|
||||
return \App\Models\Artist::query()
|
||||
->where('name', 'like', "%{$request->input('search')}%")
|
||||
->limit(20)
|
||||
->get(['id', 'name']);
|
||||
})->name('api.artists.search');
|
||||
|
||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
||||
Route::get('/dashboard', AdminDashboard::class)->name('dashboard');
|
||||
@ -36,6 +43,7 @@ Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function ()
|
||||
Route::get('/artists', function () {
|
||||
return view('livewire.admin.artists');
|
||||
})->name('artists');
|
||||
|
||||
Route::get('/artists-table', ArtistTable::class)->name('artists-table');
|
||||
|
||||
Route::get('/songs', function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user