diff --git a/.DS_Store b/.DS_Store index 7df8564..2cfe8e5 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/Imports/ArtistDataImport.php b/app/Imports/ArtistDataImport.php index 0a7cd80..4680585 100644 --- a/app/Imports/ArtistDataImport.php +++ b/app/Imports/ArtistDataImport.php @@ -23,21 +23,31 @@ class ArtistDataImport implements ToCollection, WithHeadingRow, WithChunkReading } public function collection(Collection $rows) { - $toInsert = []; + // 建立現有歌手名稱的查找表,避免重複建立 + static $existingNames = null; + if ($existingNames === null) { + $existingNames = array_flip(array_map('trim', Artist::pluck('name')->all())); + } + + $toInsert = []; + foreach ($rows as $row) { $name=trim($row['歌手姓名'] ?? ''); if (empty($name)) continue; - + + // 若資料庫已有該名稱,跳過 + if (isset($existingNames[$name])) continue; + // 字元處理 $simplified = ChineseNameConverter::convertToSimplified($name); - if (!array_key_exists('歌手注音', $row)) { + if (!$row->has('歌手注音')) { $phoneticAbbr = ChineseNameConverter::getKTVZhuyinAbbr($simplified); } else { $phoneticAbbr = trim($row['歌手注音']); } $pinyinAbbr = ChineseNameConverter::getKTVPinyinAbbr($simplified); - if (!array_key_exists('歌手注音', $row)) { + if (!$row->has('歌手筆畫')) { $chars = preg_split('//u', $name, -1, PREG_SPLIT_NO_EMPTY); $firstChar = $chars[0] ?? null; $strokesAbbr = $firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null; @@ -45,6 +55,7 @@ class ArtistDataImport implements ToCollection, WithHeadingRow, WithChunkReading $strokesAbbr = trim($row['歌手筆畫']); } // 準備 song 資料 + $now = now(); $toInsert[] = [ 'name' => $name, 'category' => ArtistCategory::tryFrom(trim($row['歌手分類'] ?? '未定義')) ?? ArtistCategory::Unset, @@ -52,8 +63,13 @@ class ArtistDataImport implements ToCollection, WithHeadingRow, WithChunkReading 'phonetic_abbr' => $phoneticAbbr, 'pinyin_abbr' => $pinyinAbbr, 'strokes_abbr' => $strokesAbbr, - 'enable' =>trim($row['狀態'] ?? 1) + 'enable' =>trim($row['狀態'] ?? 1), + 'created_at' => $now, + 'updated_at' => $now, ]; + + // 新增到快取,避免後面重複匯入 + $existingNames[$name] = true; } Artist::insert($toInsert); } diff --git a/app/Imports/SongDataImport.php b/app/Imports/SongDataImport.php index bf68797..ab75b46 100644 --- a/app/Imports/SongDataImport.php +++ b/app/Imports/SongDataImport.php @@ -8,12 +8,15 @@ use App\Models\SongCategory; use App\Enums\ArtistCategory; use App\Enums\SongLanguageType; use App\Enums\SongSituation; +use App\Helpers\ChineseNameConverter; +use App\Helpers\ChineseStrokesConverter; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\Support\Facades\Log; use Maatwebsite\Excel\Concerns\ToCollection; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Concerns\WithChunkReading; +use Maatwebsite\Excel\Imports\HeadingRowFormatter; class SongDataImport implements ToCollection, WithHeadingRow, WithChunkReading { @@ -22,13 +25,22 @@ class SongDataImport implements ToCollection, WithHeadingRow, WithChunkReading public function __construct() { + // 關閉 heading row 格式化 + HeadingRowFormatter::default('none'); // 快取分類代碼對應 ID $this->categoryMap = SongCategory::pluck('id', 'code')->toArray(); } public function collection(Collection $rows) { - $songsToInsert = []; + // 建立現有歌手名稱的查找表,避免重複建立 + static $existingIDs = null; + + if ($existingIDs === null) { + $existingIDs = array_flip(array_map('trim', Song::pluck('id')->all())); + } + + $ToInsert = []; $artistMap = []; // [song_id => [artist_id]] $categoryMap = []; // [song_id => [category_id]] @@ -38,32 +50,69 @@ class SongDataImport implements ToCollection, WithHeadingRow, WithChunkReading if (!$songId) { continue; } + // 若資料庫已有該編號,跳過 + if (isset($existingIDs[$songId])) continue; + + // 字元處理 + $songName=trim($row['歌名'] ?? ''); + $simplified=ChineseNameConverter::convertToSimplified($songName);// 繁體轉簡體 + if (!$row->has('注音')) { + $phoneticAbbr = ChineseNameConverter::getKTVZhuyinAbbr($simplified);// 注音符號 + } else { + $phoneticAbbr = trim($row['注音']); + } + if (!$row->has('拼音')) { + $pinyinAbbr = ChineseNameConverter::getKTVPinyinAbbr($simplified);// 拼音首字母 + } else { + $pinyinAbbr = trim($row['拼音']); + } + if (!$row->has('kk3')) {//歌名第一個字筆畫 + $chars = preg_split('//u', $songName, -1, PREG_SPLIT_NO_EMPTY); + $firstChar = $chars[0] ?? null; + $strokesAbbr=$firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null; + } else { + $strokesAbbr=trim($row['kk3'] ?? 0); + } + if (!$row->has('kk4')) {//歌名字數 + $songNumber = mb_strlen($songName, 'UTF-8'); + } else { + $songNumber=trim($row['kk4'] ?? 0); + } // 準備 song 資料 - $songsToInsert[] = [ + $ToInsert[] = [ 'id' => $songId, - 'name' => trim($row['歌名'] ?? ''), + 'name' => $songName, 'adddate' => trim($row['日期'] ?? null), 'filename' => trim($row['檔名'] ?? ''), 'language_type' => SongLanguageType::tryFrom(trim($row['語別'] ?? '')) ?? SongLanguageType::Unset, - 'db_change' => trim($row['分貝增減'] ?? 0), - 'vocal' => trim($row['人聲'] ?? 0), - 'situation' => SongSituation::tryFrom(trim($row['情境'] ?? '')) ?? SongSituation::Unset, + 'db_change' => trim($row['kk2'] ?? 0),//分貝增減 + 'vocal' => trim($row['kk6'] ?? 0),//人聲 + 'situation' => SongSituation::tryFrom(trim($row['kk7'] ?? '')) ?? SongSituation::Unset,//情境 'copyright01' => trim($row['版權01'] ?? ''), 'copyright02' => trim($row['版權02'] ?? ''), - 'note01' => trim($row['備註01'] ?? ''), - 'note02' => trim($row['備註02'] ?? ''), - 'note03' => trim($row['備註03'] ?? ''), - 'note04' => trim($row['備註04'] ?? ''), + 'note01' => trim($row['版權03'] ?? ''), + 'note02' => trim($row['版權04'] ?? ''), + 'note03' => trim($row['版權05'] ?? ''), + 'note04' => trim($row['版權06'] ?? ''), 'enable' => trim($row['狀態'] ?? 1), + + 'simplified' => $simplified, + 'phonetic_abbr' => $phoneticAbbr, + 'pinyin_abbr' => $pinyinAbbr, + 'strokes_abbr' => $strokesAbbr, + 'song_number' => $songNumber, + 'song_counts' => trim($row['點播次數'] ?? 0), ]; - // 歌星 A/B 處理 foreach (['歌星A', '歌星B'] as $key) { $artistName = trim($row[$key] ?? ''); if ($artistName === '') continue; - + + // 若是歌星B,且與歌星A相同,則跳過 + if ($key === '歌星B' && $artistName === trim($row['歌星A'] ?? '')) continue; + $artistId = $this->getOrCreateArtistId($artistName); $artistMap[$songId][] = $artistId; } @@ -78,10 +127,13 @@ class SongDataImport implements ToCollection, WithHeadingRow, WithChunkReading } } } + + // 新增到快取,避免後面重複匯入 + $existingIDs[$songId] = true; } // 寫入資料庫 - Song::insert($songsToInsert); + Song::insert($ToInsert); // 同步關聯(建議可用事件或批次處理) foreach ($artistMap as $songId => $artistIds) { @@ -115,7 +167,7 @@ class SongDataImport implements ToCollection, WithHeadingRow, WithChunkReading public function chunkSize(): int { - return 1000; + return 100; } public function headingRow(): int diff --git a/app/Jobs/ImportArtistJob.php b/app/Jobs/ImportArtistJob.php index 1ed62af..22d5a1c 100644 --- a/app/Jobs/ImportArtistJob.php +++ b/app/Jobs/ImportArtistJob.php @@ -33,6 +33,8 @@ class ImportArtistJob implements ShouldQueue */ public function handle(): void { + ini_set('memory_limit', '-1'); // ✅ 增加記憶體限制 + Excel::import(new ArtistDataImport, $this->filePath); // 匯入完成後刪除檔案 if (Storage::exists($this->filePath)) { diff --git a/app/Jobs/ImportSongJob.php b/app/Jobs/ImportSongJob.php new file mode 100644 index 0000000..d6bb70a --- /dev/null +++ b/app/Jobs/ImportSongJob.php @@ -0,0 +1,44 @@ +filePath = $filePath; + } + + /** + * Execute the job. + */ + public function handle(): void + { + ini_set('memory_limit', '-1'); // ✅ 增加記憶體限制 + + Excel::import(new SongDataImport, $this->filePath); + // 匯入完成後刪除檔案 + if (Storage::exists($this->filePath)) { + Storage::delete($this->filePath); + } + } +} diff --git a/app/Livewire/Admin/ArtistForm.php b/app/Livewire/Admin/ArtistForm.php index b216d93..f799cdb 100644 --- a/app/Livewire/Admin/ArtistForm.php +++ b/app/Livewire/Admin/ArtistForm.php @@ -2,14 +2,19 @@ namespace App\Livewire\Admin; -use Livewire\Component; use Illuminate\Validation\Rule; use Illuminate\Support\Facades\Auth; + +use Livewire\Component; +use WireUi\Traits\WireUiActions; + use App\Models\Artist; use App\Enums\ArtistCategory; class ArtistForm extends Component { + use WireUiActions; + protected $listeners = ['openModal','closeModal', 'deleteArtist']; public bool $canCreate; @@ -65,19 +70,19 @@ class ArtistForm extends Component if ($this->canEdit) { $artist = Artist::findOrFail($this->artistId); $artist->update($this->fields); - $this->dispatch('notify', [ + $this->notification()->send([ + 'icon' => 'success', 'title' => '成功', 'description' => '歌手已更新', - 'icon' => 'success', ]); } } else { if ($canCreate) { $artist = Artist::create($this->fields); - $this->dispatch('notify', [ + $this->notification()->send([ + 'icon' => 'success', 'title' => '成功', 'description' => '歌手已新增', - 'icon' => 'success', ]); } } @@ -90,7 +95,12 @@ class ArtistForm extends Component { if ($this->canDelect) { Artist::findOrFail($id)->delete(); - session()->flash('message', '歌手已刪除'); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '歌手已刪除', + ]); + $this->dispatch('pg:eventRefresh-artist-table'); } } diff --git a/app/Livewire/Admin/ArtistImportData.php b/app/Livewire/Admin/ArtistImportData.php index 9b94084..08be024 100644 --- a/app/Livewire/Admin/ArtistImportData.php +++ b/app/Livewire/Admin/ArtistImportData.php @@ -3,14 +3,17 @@ namespace App\Livewire\Admin; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\File; +use WireUi\Traits\WireUiActions; use Livewire\Component; use Livewire\WithFileUploads; use App\Jobs\ImportArtistJob; -use Illuminate\Support\Facades\Storage; + class ArtistImportData extends Component { - use WithFileUploads; + use WithFileUploads, WireUiActions; protected $listeners = ['openModal','closeModal']; @@ -20,6 +23,8 @@ class ArtistImportData extends Component public $file; + public string|null $tmpPath = null; + public function mount() { $this->canCreate = Auth::user()?->can('song-edit') ?? false; @@ -29,8 +34,11 @@ class ArtistImportData extends Component { $this->showModal = true; } + public function closeModal() { + $this->deleteTmpFile(); // 關閉 modal 時刪除暫存檔案 + $this->reset(['file', 'tmpPath']); $this->showModal = false; } @@ -41,15 +49,28 @@ class ArtistImportData extends Component 'file' => 'required|file|mimes:csv,xlsx,xls' ]); if ($this->canCreate) { + // 取得原始 tmp 路徑 + $tmpPath = $this->file->getRealPath(); // 儲存檔案至 storage $path = $this->file->storeAs('imports', uniqid() . '_' . $this->file->getClientOriginalName()); // 丟到 queue 執行 ImportArtistJob::dispatch($path); - - $this->reset('file'); + + $this->notification()->send([ + 'icon' => 'info', + 'title' => $this->file->getClientOriginalName(), + 'description' => '已排入背景匯入作業,請稍候查看結果', + ]); + $this->deleteTmpFile(); // 匯入後也順便刪除 tmp 檔 + $this->reset(['file', 'tmpPath']); $this->showModal = false; - session()->flash('message', '已排入背景匯入作業,請稍候查看結果'); + } + } + protected function deleteTmpFile() + { + if ($this->tmpPath && File::exists($this->tmpPath)) { + File::delete($this->tmpPath); } } diff --git a/app/Livewire/Admin/ArtistTable.php b/app/Livewire/Admin/ArtistTable.php index dc1ebeb..e4f39dd 100644 --- a/app/Livewire/Admin/ArtistTable.php +++ b/app/Livewire/Admin/ArtistTable.php @@ -19,9 +19,12 @@ use PowerComponents\LivewirePowerGrid\Traits\WithExport; use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable; use PowerComponents\LivewirePowerGrid\Facades\Rule; use Livewire\Attributes\On; +use WireUi\Traits\WireUiActions; final class ArtistTable extends PowerGridComponent { + use WireUiActions; + public string $tableName = 'artist-table'; public bool $canCreate; public bool $canEdit; @@ -166,12 +169,24 @@ final class ArtistTable extends PowerGridComponent $this->noUpdated($id,$field,$value); } } + #[On('onUpdatedToggleable')] + public function onUpdatedToggleable($id, $field, $value): void + { + if (in_array($field,['enable']) && $this->canEdit) { + $this->noUpdated($id,$field,$value); + } + } private function noUpdated($id,$field,$value){ $artist = Artist::find($id); if ($artist) { $artist->{$field} = $value; $artist->save(); // 明確觸發 saving } + $this->notification()->send([ + 'icon' => 'success', + 'title' => $id.'.'.__('artists.'.$field).':'.$value, + 'description' => '已經寫入', + ]); } public function filters(): array diff --git a/app/Livewire/Admin/RoleForm.php b/app/Livewire/Admin/RoleForm.php index dbf0973..aacfad4 100644 --- a/app/Livewire/Admin/RoleForm.php +++ b/app/Livewire/Admin/RoleForm.php @@ -2,15 +2,25 @@ namespace App\Livewire\Admin; +use Illuminate\Validation\Rule; +use Illuminate\Support\Facades\Auth; + use Livewire\Component; +use WireUi\Traits\WireUiActions; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; class RoleForm extends Component { + use WireUiActions; + protected $listeners = ['openCreateRoleModal','openEditRoleModal', 'deleteRole']; + public bool $canCreate; + public bool $canEdit; + public bool $canDelect; + public $showCreateModal=false; public ?int $roleId = null; public $name = ''; @@ -22,6 +32,9 @@ class RoleForm extends Component public function mount() { $this->permissions = Permission::all(); + $this->canCreate = Auth::user()?->can('role-edit') ?? false; + $this->canEdit = Auth::user()?->can('role-edit') ?? false; + $this->canDelect = Auth::user()?->can('role-delete') ?? false; } public function openCreateRoleModal() @@ -47,14 +60,26 @@ class RoleForm extends Component ]); if ($this->roleId) { - $role = Role::findOrFail($this->roleId); - $role->update(['name' => $this->name]); - $role->syncPermissions($this->selectedPermissions); - session()->flash('message', '角色已更新'); + if ($this->canEdit) { + $role = Role::findOrFail($this->roleId); + $role->update(['name' => $this->name]); + $role->syncPermissions($this->selectedPermissions); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '角色已更新', + ]); + } } else { - $role = Role::create(['name' => $this->name]); - $role->syncPermissions($this->selectedPermissions); - session()->flash('message', '角色已新增'); + if ($canCreate) { + $role = Role::create(['name' => $this->name]); + $role->syncPermissions($this->selectedPermissions); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '角色已新增', + ]); + } } $this->resetFields(); @@ -64,8 +89,15 @@ class RoleForm extends Component public function deleteRole($id) { - Role::findOrFail($id)->delete(); - session()->flash('message', '角色已刪除'); + if ($this->canDelect) { + Role::findOrFail($id)->delete(); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '角色已刪除', + ]); + $this->dispatch('pg:eventRefresh-role-table'); + } } public function resetFields() diff --git a/app/Livewire/Admin/RoleTable.php b/app/Livewire/Admin/RoleTable.php index 01bec58..b575225 100644 --- a/app/Livewire/Admin/RoleTable.php +++ b/app/Livewire/Admin/RoleTable.php @@ -13,9 +13,13 @@ use PowerComponents\LivewirePowerGrid\Facades\Filter; use PowerComponents\LivewirePowerGrid\Facades\PowerGrid; use PowerComponents\LivewirePowerGrid\PowerGridFields; use PowerComponents\LivewirePowerGrid\PowerGridComponent; +use Livewire\Attributes\On; +use WireUi\Traits\WireUiActions; final class RoleTable extends PowerGridComponent { + use WireUiActions; + public string $tableName = 'role-table'; public bool $canCreate; public bool $canEdit; @@ -128,6 +132,11 @@ final class RoleTable extends PowerGridComponent $role->{$field} = $value; $role->save(); // 明確觸發 saving } + $this->notification()->send([ + 'icon' => 'success', + 'title' => $id.'.'.__('roles.'.$field).':'.$value, + 'description' => '已經寫入', + ]); } public function filters(): array { diff --git a/app/Livewire/Admin/SongForm.php b/app/Livewire/Admin/SongForm.php index 168f1c3..79ac39c 100644 --- a/app/Livewire/Admin/SongForm.php +++ b/app/Livewire/Admin/SongForm.php @@ -2,7 +2,11 @@ namespace App\Livewire\Admin; +use Illuminate\Validation\Rule; +use Illuminate\Support\Facades\Auth; + use Livewire\Component; +use WireUi\Traits\WireUiActions; use App\Enums\SongLanguageType; use App\Enums\SongSituation; @@ -11,7 +15,13 @@ use App\Models\SongCategory; class SongForm extends Component { + use WireUiActions; + protected $listeners = ['openModal','closeModal', 'deleteSong']; + + public bool $canCreate; + public bool $canEdit; + public bool $canDelect; public bool $showModal = false; @@ -88,10 +98,18 @@ class SongForm extends Component if ($this->songId) { $song = Song::findOrFail($this->songId); $song->update($this->fields); - session()->flash('message', '歌曲已更新'); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '歌曲已更新', + ]); } else { $song = Song::create($this->fields); - session()->flash('message', '歌曲已新增'); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '歌曲已新增', + ]); } // ⭐ 同步多對多關聯 $song->artists()->sync($this->selectedArtists ?? []); @@ -105,7 +123,11 @@ class SongForm extends Component public function deleteSong($id) { Song::findOrFail($id)->delete(); - session()->flash('message', '歌曲已刪除'); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '歌曲已刪除', + ]); } public function resetFields() diff --git a/app/Livewire/Admin/SongImportData.php b/app/Livewire/Admin/SongImportData.php index 2e0c367..443ecb2 100644 --- a/app/Livewire/Admin/SongImportData.php +++ b/app/Livewire/Admin/SongImportData.php @@ -3,14 +3,17 @@ namespace App\Livewire\Admin; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\File; +use WireUi\Traits\WireUiActions; use Livewire\Component; use Livewire\WithFileUploads; -use Maatwebsite\Excel\Facades\Excel; -use App\Imports\SongDataImport; +use App\Jobs\ImportSongJob; + class SongImportData extends Component { - use WithFileUploads; + use WithFileUploads, WireUiActions; protected $listeners = ['openModal','closeModal']; @@ -20,6 +23,8 @@ class SongImportData extends Component public $file; + public string|null $tmpPath = null; + public function mount() { $this->canCreate = Auth::user()?->can('song-edit') ?? false; @@ -29,8 +34,11 @@ class SongImportData extends Component { $this->showModal = true; } + public function closeModal() { + $this->deleteTmpFile(); // 關閉 modal 時刪除暫存檔案 + $this->reset(['file', 'tmpPath']); $this->showModal = false; } @@ -41,13 +49,28 @@ class SongImportData extends Component 'file' => 'required|file|mimes:csv,xlsx,xls' ]); if ($this->canCreate) { - $import = new SongDataImport(); - Excel::import($import, $this->file); - $success = $import->successCount; - $fail = $import->failCount; - $this->reset('file'); - $this->showModal =false; - session()->flash('message', '匯入完成:成功 $success 筆,失敗 $fail 筆。'); + // 取得原始 tmp 路徑 + $tmpPath = $this->file->getRealPath(); + // 儲存檔案至 storage + $path = $this->file->storeAs('imports', uniqid() . '_' . $this->file->getClientOriginalName()); + + // 丟到 queue 執行 + ImportSongJob::dispatch($path); + + $this->notification()->send([ + 'icon' => 'info', + 'title' => $this->file->getClientOriginalName(), + 'description' => '已排入背景匯入作業,請稍候查看結果', + ]); + $this->deleteTmpFile(); // 匯入後也順便刪除 tmp 檔 + $this->reset(['file', 'tmpPath']); + $this->showModal = false; + } + } + protected function deleteTmpFile() + { + if ($this->tmpPath && File::exists($this->tmpPath)) { + File::delete($this->tmpPath); } } diff --git a/app/Livewire/Admin/SongTable.php b/app/Livewire/Admin/SongTable.php index 10f057f..b3e2a09 100644 --- a/app/Livewire/Admin/SongTable.php +++ b/app/Livewire/Admin/SongTable.php @@ -20,9 +20,12 @@ use PowerComponents\LivewirePowerGrid\Traits\WithExport; use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable; use PowerComponents\LivewirePowerGrid\Facades\Rule; use Livewire\Attributes\On; +use WireUi\Traits\WireUiActions; final class SongTable extends PowerGridComponent { + use WireUiActions; + public string $tableName = 'song-table'; public bool $canCreate; public bool $canEdit; @@ -203,7 +206,14 @@ final class SongTable extends PowerGridComponent { $this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))'); if($this->checkboxValues){ - Song::destroy($this->checkboxValues); + foreach ($this->checkboxValues as $id) { + $song = Song::find($id); + if ($song) { + $song->artists()->detach(); + $song->categories()->detach(); + $song->delete(); + } + } $this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface. } } @@ -238,6 +248,11 @@ final class SongTable extends PowerGridComponent $song->{$field} = $value; $song->save(); // 明確觸發 saving } + $this->notification()->send([ + 'icon' => 'success', + 'title' => $id.'.'.__('songs.'.$field).':'.$value, + 'description' => '已經寫入', + ]); } diff --git a/app/Livewire/Admin/UserForm.php b/app/Livewire/Admin/UserForm.php index f553f9c..ddb8c7a 100644 --- a/app/Livewire/Admin/UserForm.php +++ b/app/Livewire/Admin/UserForm.php @@ -2,7 +2,11 @@ namespace App\Livewire\Admin; +use Illuminate\Validation\Rule; +use Illuminate\Support\Facades\Auth; + use Livewire\Component; +use WireUi\Traits\WireUiActions; use App\Models\User; use App\Enums\UserGender; @@ -11,10 +15,15 @@ use Spatie\Permission\Models\Role; class UserForm extends Component { + use WireUiActions; + protected $listeners = ['openCreateUserModal','openEditUserModal', 'deleteUser']; - public bool $showCreateModal = false; + public bool $canCreate; + public bool $canEdit; + public bool $canDelect; + public bool $showCreateModal = false; public array $genderOptions =[]; public array $statusOptions =[]; @@ -52,6 +61,9 @@ class UserForm extends Component 'value' => $status->value, ])->toArray(); $this->rolesOptions = Role::all(); + $this->canCreate = Auth::user()?->can('user-edit') ?? false; + $this->canEdit = Auth::user()?->can('user-edit') ?? false; + $this->canDelect = Auth::user()?->can('user-delete') ?? false; } public function openCreateUserModal() @@ -72,17 +84,29 @@ class UserForm extends Component public function save() { - $this->validate(); + //$this->validate(); if ($this->userId) { - $user = User::findOrFail($this->userId); - $user->update($this->fields); - $user->syncRoles($this->selectedRoles); - session()->flash('message', '使用者已更新'); + if ($this->canEdit) { + $user = User::findOrFail($this->userId); + $user->update($this->fields); + $user->syncRoles($this->selectedRoles); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '使用者已更新', + ]); + } } else { - $user = User::create($this->fields); - $user->syncRoles($this->selectedRoles); - session()->flash('message', '使用者已新增'); + if ($canCreate) { + $user = User::create($this->fields); + $user->syncRoles($this->selectedRoles); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '使用者已新增', + ]); + } } $this->resetFields(); @@ -92,8 +116,15 @@ class UserForm extends Component public function deleteUser($id) { - User::findOrFail($id)->delete(); - session()->flash('message', '使用者已刪除'); + if ($this->canDelect) { + User::findOrFail($id)->delete(); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '使用者已刪除', + ]); + $this->dispatch('pg:eventRefresh-user-table'); + } } public function resetFields() diff --git a/app/Livewire/Admin/UserTable.php b/app/Livewire/Admin/UserTable.php index 975eb7a..10bb107 100644 --- a/app/Livewire/Admin/UserTable.php +++ b/app/Livewire/Admin/UserTable.php @@ -19,9 +19,11 @@ use PowerComponents\LivewirePowerGrid\PowerGridComponent; use PowerComponents\LivewirePowerGrid\Components\SetUp\Exportable; use PowerComponents\LivewirePowerGrid\Facades\Rule; use Livewire\Attributes\On; +use WireUi\Traits\WireUiActions; final class UserTable extends PowerGridComponent { + use WireUiActions; //use WithExport ; public string $tableName = 'user-table'; @@ -174,7 +176,7 @@ final class UserTable extends PowerGridComponent if ($this->canDelect) { $this->js('alert(window.pgBulkActions.get(\'' . $this->tableName . '\'))'); if($this->checkboxValues){ - Artist::destroy($this->checkboxValues); + User::destroy($this->checkboxValues); $this->js('window.pgBulkActions.clearAll()'); // clear the count on the interface. } } @@ -202,11 +204,16 @@ final class UserTable extends PowerGridComponent } } private function noUpdated($id,$field,$value){ - $artist = Artist::find($id); - if ($artist) { - $artist->{$field} = $value; - $artist->save(); // 明確觸發 saving + $user = User::find($id); + if ($user) { + $user->{$field} = $value; + $user->save(); // 明確觸發 saving } + $this->notification()->send([ + 'icon' => 'success', + 'title' => $id.'.'.__('users.'.$field).':'.$value, + 'description' => '已經寫入', + ]); } public function filters(): array { diff --git a/app/Models/Song.php b/app/Models/Song.php index f40efd5..50a3319 100644 --- a/app/Models/Song.php +++ b/app/Models/Song.php @@ -31,6 +31,7 @@ class Song extends Model 'phonetic_abbr', 'pinyin_abbr', 'strokes_abbr', + 'song_number', 'song_counts', ]; @@ -77,6 +78,7 @@ class Song extends Model $chars = preg_split('//u', $song->name, -1, PREG_SPLIT_NO_EMPTY); $firstChar = $chars[0] ?? null; $song->strokes_abbr=$firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null; + $song->song_number = mb_strlen($song->name, 'UTF-8'); }); } } diff --git a/database/migrations/2025_04_23_031630_create_songs_table.php b/database/migrations/2025_04_23_031630_create_songs_table.php index 5341249..2ae2a76 100644 --- a/database/migrations/2025_04_23_031630_create_songs_table.php +++ b/database/migrations/2025_04_23_031630_create_songs_table.php @@ -31,6 +31,7 @@ return new class extends Migration $table->string('phonetic_abbr')->comment('歌曲注音'); $table->string('pinyin_abbr')->comment('歌曲拼音'); $table->integer('strokes_abbr')->default(0)->comment('歌曲筆劃'); + $table->integer('song_number')->default(0)->comment('歌曲字數'); $table->integer('song_counts')->default(0)->comment('點播次數'); $table->timestamps(); }); diff --git a/resources/views/livewire/admin/artist-import-data.blade.php b/resources/views/livewire/admin/artist-import-data.blade.php index 5793060..2d4cf55 100644 --- a/resources/views/livewire/admin/artist-import-data.blade.php +++ b/resources/views/livewire/admin/artist-import-data.blade.php @@ -1,4 +1,4 @@ - + {{-- 說明區塊 --}}
diff --git a/resources/views/livewire/admin/artists.blade.php b/resources/views/livewire/admin/artists.blade.php index b4a9f1a..6fb4311 100644 --- a/resources/views/livewire/admin/artists.blade.php +++ b/resources/views/livewire/admin/artists.blade.php @@ -1,18 +1,6 @@ - - - - - {{-- 單一 Livewire 元件,內含資料表與 Modal --}} - - + diff --git a/resources/views/livewire/admin/roles.blade.php b/resources/views/livewire/admin/roles.blade.php index a95e290..49ae7ed 100644 --- a/resources/views/livewire/admin/roles.blade.php +++ b/resources/views/livewire/admin/roles.blade.php @@ -1,17 +1,6 @@ - @if (session()->has('message')) - - - @endif - - {{-- 單一 Livewire 元件,內含資料表與 Modal --}} + \ No newline at end of file diff --git a/resources/views/livewire/admin/song-import-data.blade.php b/resources/views/livewire/admin/song-import-data.blade.php index bf91eb5..6583108 100644 --- a/resources/views/livewire/admin/song-import-data.blade.php +++ b/resources/views/livewire/admin/song-import-data.blade.php @@ -1,4 +1,4 @@ - + {{-- resources/views/components/import-format-info.blade.php --}} @@ -26,16 +26,6 @@ 歌曲名稱 小幸運 - - 檔名 - 歌曲檔名 - 993794.mpg - - - 日期 - 新增日期(格式:YYYY-MM-DD) - 2015-08-14 - 歌星A 可填入歌手名稱 @@ -46,60 +36,70 @@ 可填入歌手名稱 + + 檔名 + 歌曲檔名 + 993794.mpg + + + 日期 + 新增日期(格式:YYYY-MM-DD) + 2015-08-14 + + + 分類 + 可填入多個分類代碼(用 , 分隔)A1(情歌),B1(選秀),C1(串燒),D1(90年),E1(懷念),F1(大陸) + + + + 注音 + 歌曲注音 + ㄒㄒㄩ + + + 拼音 + 歌曲拼音 + XXY + 語別 可用語別:國語、台語、英語、日語、粵語、韓語、越語、客語、其他 等 國語 - 分類 - 可填入多個分類代碼(用 , 分隔)A1(情歌),B1(選秀),C1(串燒),D1(90年),E1(懷念),F1(大陸) - A1,B1,C1,D1,E1,F1 - - - 分貝增減 - 歌曲播放時的音量調整(正數為增加,負數為減少) - -2 - - - 人聲 - 是否有人聲(1:有人聲,0:純音樂) - 1 - - - 情境 - 可標註使用情境,例如:婚禮、派對、練唱 - + 點播次數 + 記錄此歌曲被點播的次數 + 519 版權01 版權擁有者或公司名稱 - 華研國際 + 揚聲 版權02 次要版權擁有者或管理單位 - 滾石唱片 + - 備註01 + 版權03 其他補充資訊,例如:原唱者、翻唱說明等 - 原唱:田馥甄 + 原影 - 備註02 + 版權04 其他補充資訊 - 翻唱版 + - 備註03 + 版權05 其他補充資訊 - 高音質 + - 備註04 + 版權06 其他補充資訊 - 2023重錄版 + 狀態 @@ -107,9 +107,29 @@ 1 - 點播次數 - 記錄此歌曲被點播的次數 - 128 + kk2 + 歌曲播放時的音量調整(正數為增加,負數為減少) + + + + kk3 + 歌名第一個字筆畫 + 3 + + + kk4 + 歌名字數 + 3 + + + kk6 + 是否有人聲(1:有人聲,0:純音樂) + 1 + + + kk7 + 可標註使用情境,例如:浪漫、柔和、動感、明亮 + 柔和 diff --git a/resources/views/livewire/admin/songs.blade.php b/resources/views/livewire/admin/songs.blade.php index eacd2ee..0fda345 100644 --- a/resources/views/livewire/admin/songs.blade.php +++ b/resources/views/livewire/admin/songs.blade.php @@ -1,17 +1,6 @@ - @if (session()->has('message')) - - - @endif - - {{-- 單一 Livewire 元件,內含資料表與 Modal --}} + diff --git a/resources/views/livewire/admin/users.blade.php b/resources/views/livewire/admin/users.blade.php index c57a416..33c11d8 100644 --- a/resources/views/livewire/admin/users.blade.php +++ b/resources/views/livewire/admin/users.blade.php @@ -1,17 +1,6 @@ - @if (session()->has('message')) - - - @endif - - {{-- 單一 Livewire 元件,內含資料表與 Modal --}} + \ No newline at end of file