song 滙入大量資料問題修正 20250509
This commit is contained in:
parent
c004ce0504
commit
8c59fced90
BIN
app/.DS_Store
vendored
BIN
app/.DS_Store
vendored
Binary file not shown.
@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Models\Artist;
|
||||
use App\Enums\ArtistCategory;
|
||||
use App\Helpers\ChineseNameConverter;
|
||||
use App\Helpers\ChineseStrokesConverter;
|
||||
use Illuminate\Support\Collection;
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
|
||||
|
||||
class ArtistDataImport implements ToCollection, WithHeadingRow, WithChunkReading, WithBatchInserts
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 關閉 heading row 格式化
|
||||
HeadingRowFormatter::default('none');
|
||||
}
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
// 建立現有歌手名稱的查找表,避免重複建立
|
||||
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 (!$row->has('歌手注音')) {
|
||||
$phoneticAbbr = ChineseNameConverter::getKTVZhuyinAbbr($simplified);
|
||||
} else {
|
||||
$phoneticAbbr = trim($row['歌手注音']);
|
||||
}
|
||||
$pinyinAbbr = ChineseNameConverter::getKTVPinyinAbbr($simplified);
|
||||
if (!$row->has('歌手筆畫')) {
|
||||
$chars = preg_split('//u', $name, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$firstChar = $chars[0] ?? null;
|
||||
$strokesAbbr = $firstChar ? ChineseStrokesConverter::getStrokes($firstChar) : null;
|
||||
} else {
|
||||
$strokesAbbr = trim($row['歌手筆畫']);
|
||||
}
|
||||
// 準備 song 資料
|
||||
$now = now();
|
||||
$toInsert[] = [
|
||||
'name' => $name,
|
||||
'category' => ArtistCategory::tryFrom(trim($row['歌手分類'] ?? '未定義')) ?? ArtistCategory::Unset,
|
||||
'simplified' => $simplified,
|
||||
'phonetic_abbr' => $phoneticAbbr,
|
||||
'pinyin_abbr' => $pinyinAbbr,
|
||||
'strokes_abbr' => $strokesAbbr,
|
||||
'enable' =>trim($row['狀態'] ?? 1),
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
// 新增到快取,避免後面重複匯入
|
||||
$existingNames[$name] = true;
|
||||
}
|
||||
Artist::insert($toInsert);
|
||||
}
|
||||
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
public function batchSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
public function headingRow(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
40
app/Imports/DataImport.php
Normal file
40
app/Imports/DataImport.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||
use Illuminate\Support\Collection;
|
||||
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
|
||||
use App\Jobs\ImportArtistChunkJob;
|
||||
use App\Jobs\ImportSongChunkJob;
|
||||
|
||||
class DataImport implements ToCollection, WithHeadingRow, WithChunkReading
|
||||
{
|
||||
protected string $modelName;
|
||||
public function __construct(string $modelName)
|
||||
{
|
||||
HeadingRowFormatter::default('none');
|
||||
$this->modelName= $modelName;
|
||||
}
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
if($this->modelName=='Song'){
|
||||
ImportSongChunkJob::dispatch($rows);
|
||||
}else if($this->modelName=='Artist'){
|
||||
ImportArtistChunkJob::dispatch($rows);
|
||||
}else{
|
||||
|
||||
}
|
||||
}
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public function headingRow(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Models\Song;
|
||||
use App\Models\Artist;
|
||||
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
|
||||
{
|
||||
protected array $artistCache = [];
|
||||
protected array $categoryMap = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 關閉 heading row 格式化
|
||||
HeadingRowFormatter::default('none');
|
||||
// 快取分類代碼對應 ID
|
||||
$this->categoryMap = SongCategory::pluck('id', 'code')->toArray();
|
||||
}
|
||||
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
foreach ($rows as $row) {
|
||||
$songId = trim($row['編號'] ?? '');
|
||||
|
||||
if (!$songId) {
|
||||
continue;
|
||||
}
|
||||
// 改為即時查詢是否已有此編號
|
||||
if (Song::where('id', $songId)->exists()) {
|
||||
continue;
|
||||
}
|
||||
// 準備 song 資料
|
||||
$song = new Song([
|
||||
'id' => $songId,
|
||||
'name' => $songName,
|
||||
'adddate' => trim($row['日期'] ?? null),
|
||||
'filename' => trim($row['檔名'] ?? ''),
|
||||
'language_type' => SongLanguageType::tryFrom(trim($row['語別'] ?? '')) ?? SongLanguageType::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['版權03'] ?? ''),
|
||||
'note02' => trim($row['版權04'] ?? ''),
|
||||
'note03' => trim($row['版權05'] ?? ''),
|
||||
'note04' => trim($row['版權06'] ?? ''),
|
||||
'enable' => trim($row['狀態'] ?? 1),
|
||||
'song_counts' => trim($row['點播次數'] ?? 0),
|
||||
]);
|
||||
|
||||
$song->save();
|
||||
|
||||
// 處理關聯 - 歌手
|
||||
$artistIds = [];
|
||||
foreach (['歌星A', '歌星B'] as $key) {
|
||||
$artistName = trim($row[$key] ?? '');
|
||||
if ($artistName === '') continue;
|
||||
|
||||
// 若是歌星B,且與歌星A相同,則跳過
|
||||
if ($key === '歌星B' && $artistName === trim($row['歌星A'] ?? '')) continue;
|
||||
|
||||
$artistIds[] = $this->getOrCreateArtistId($artistName);
|
||||
}
|
||||
$song->artists()->sync($artistIds);
|
||||
|
||||
// 分類處理(多個用 , 分隔)
|
||||
if (!empty($row['分類'])) {
|
||||
$categoryIds = [];
|
||||
$codes = explode(',', $row['分類']);
|
||||
foreach ($codes as $code) {
|
||||
$code = trim($code);
|
||||
if (isset($this->categoryMap[$code])) {
|
||||
$categoryIds[] = $this->categoryMap[$code];
|
||||
}
|
||||
}
|
||||
$song->categories()->sync($categoryIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getOrCreateArtistId(string $name): int
|
||||
{
|
||||
if (isset($this->artistCache[$name])) {
|
||||
return $this->artistCache[$name];
|
||||
}
|
||||
|
||||
$artist = Artist::firstOrCreate(
|
||||
['name' => $name],
|
||||
['category' => ArtistCategory::Unset]
|
||||
);
|
||||
|
||||
return $this->artistCache[$name] = $artist->id;
|
||||
}
|
||||
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
public function headingRow(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
52
app/Jobs/ImportArtistChunkJob.php
Normal file
52
app/Jobs/ImportArtistChunkJob.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Artist;
|
||||
use App\Enums\ArtistCategory;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ImportArtistChunkJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected Collection $rows;
|
||||
|
||||
public function __construct(Collection $rows)
|
||||
{
|
||||
$this->rows = $rows;
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
foreach ($this->rows as $index => $row) {
|
||||
try {
|
||||
$name = trim($row['歌手姓名'] ?? '');
|
||||
|
||||
if (empty($name)) {
|
||||
continue;
|
||||
}
|
||||
if (Artist::where('name', $name)->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Artist::create([
|
||||
'name' => $name,
|
||||
'category' => ArtistCategory::tryFrom(trim($row['歌手分類'] ?? '未定義')) ?? ArtistCategory::Unset,
|
||||
'enable' => trim($row['狀態'] ?? 1),
|
||||
]);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
\Log::error("Row {$index} failed: {$e->getMessage()}", [
|
||||
'row' => $row,
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Imports\ArtistDataImport;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
//use Illuminate\Foundation\Queue\Queueable;
|
||||
|
||||
class ImportArtistJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected string $filePath;
|
||||
public $timeout = 3600;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(string $filePath)
|
||||
{
|
||||
$this->filePath = $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
ini_set('memory_limit', '-1'); // ✅ 增加記憶體限制
|
||||
|
||||
Excel::import(new ArtistDataImport, $this->filePath);
|
||||
// 匯入完成後刪除檔案
|
||||
if (Storage::exists($this->filePath)) {
|
||||
Storage::delete($this->filePath);
|
||||
}
|
||||
}
|
||||
}
|
59
app/Jobs/ImportJob.php
Normal file
59
app/Jobs/ImportJob.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Imports\DataImport;
|
||||
|
||||
class ImportJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected string $modelName;
|
||||
protected string $filePath;
|
||||
public $timeout = 3600;
|
||||
public $tries = 1;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(string $filePath,string $modelName)
|
||||
{
|
||||
$this->filePath = $filePath;
|
||||
$this->modelName= $modelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
ini_set('memory_limit', '512M'); // ✅ 增加記憶體限制
|
||||
Log::info('[ImportJob] 開始處理檔案:' . $this->filePath);
|
||||
|
||||
try {
|
||||
if (!Storage::exists($this->filePath)) {
|
||||
Log::warning('[ImportJob] 檔案不存在:' . $this->filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
Excel::import(new DataImport($this->modelName), $this->filePath);
|
||||
Log::info('[ImportJob] 已提交所有 chunk 匯入任務。');
|
||||
|
||||
Storage::delete($this->filePath);
|
||||
Log::info('[ImportJob] 已刪除檔案:' . $this->filePath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error("[ImportJob] 匯入失敗:{$e->getMessage()}", [
|
||||
'file' => $this->filePath,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
102
app/Jobs/ImportSongChunkJob.php
Normal file
102
app/Jobs/ImportSongChunkJob.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Song;
|
||||
use App\Models\Artist;
|
||||
use App\Models\SongCategory;
|
||||
use App\Enums\ArtistCategory;
|
||||
use App\Enums\SongLanguageType;
|
||||
use App\Enums\SongSituation;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ImportSongChunkJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected Collection $rows;
|
||||
protected array $categoryMap = [];
|
||||
|
||||
public function __construct(Collection $rows)
|
||||
{
|
||||
$this->rows = $rows;
|
||||
$this->categoryMap = SongCategory::pluck('id', 'code')->toArray();
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
foreach ($this->rows as $index => $row) {
|
||||
$songId = trim($row['編號'] ?? '');
|
||||
|
||||
if (!$songId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 改為即時查詢是否已有此編號
|
||||
if (Song::where('id', $songId)->exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// 準備 song 資料
|
||||
$song = new Song([
|
||||
'id' => $songId,
|
||||
'name' => trim($row['歌名'] ?? ''),
|
||||
'adddate' => trim($row['日期'] ?? null),
|
||||
'filename' => trim($row['檔名'] ?? ''),
|
||||
'language_type' => SongLanguageType::tryFrom(trim($row['語別'] ?? '')) ?? SongLanguageType::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['版權03'] ?? ''),
|
||||
'note02' => trim($row['版權04'] ?? ''),
|
||||
'note03' => trim($row['版權05'] ?? ''),
|
||||
'note04' => trim($row['版權06'] ?? ''),
|
||||
'enable' => trim($row['狀態'] ?? 1),
|
||||
'song_counts' => trim($row['點播次數'] ?? 0),
|
||||
]);
|
||||
|
||||
$song->save();
|
||||
|
||||
// 處理關聯 - 歌手
|
||||
$artistIds = [];
|
||||
foreach (['歌星A', '歌星B'] as $key) {
|
||||
$artistName = trim($row[$key] ?? '');
|
||||
if ($artistName === '') continue;
|
||||
|
||||
// 若是歌星B,且與歌星A相同,則跳過
|
||||
if ($key === '歌星B' && $artistName === trim($row['歌星A'] ?? '')) continue;
|
||||
|
||||
$artistIds[] = $this->getOrCreateArtistId($artistName);
|
||||
}
|
||||
$song->artists()->sync($artistIds);
|
||||
|
||||
// 分類處理(多個用 , 分隔)
|
||||
if (!empty($row['分類'])) {
|
||||
$categoryIds = [];
|
||||
$codes = explode(',', $row['分類']);
|
||||
foreach ($codes as $code) {
|
||||
$code = trim($code);
|
||||
if (isset($this->categoryMap[$code])) {
|
||||
$categoryIds[] = $this->categoryMap[$code];
|
||||
}
|
||||
}
|
||||
$song->categories()->sync($categoryIds);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
\Log::error("Row {$index} failed: {$e->getMessage()}", [
|
||||
'row' => $row,
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Imports\SongDataImport;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
//use Illuminate\Foundation\Queue\Queueable;
|
||||
|
||||
class ImportSongJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected string $filePath;
|
||||
//public $timeout = 36000;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(string $filePath)
|
||||
{
|
||||
$this->filePath = $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
//ini_set('memory_limit', '-1'); // 無限記憶體,適合大量匯入
|
||||
|
||||
try {
|
||||
Excel::import(new SongDataImport, $this->filePath);
|
||||
|
||||
// 匯入成功後再刪檔案
|
||||
if (Storage::exists($this->filePath)) {
|
||||
Storage::delete($this->filePath);
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
// 寫入錯誤日誌
|
||||
\Log::error('ImportSongJob failed: ' . $e->getMessage(), [
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'file' => $this->filePath
|
||||
]);
|
||||
|
||||
// ❗重要:不要刪除檔案,讓失敗時可以 retry 使用同一份檔案
|
||||
throw $e; // 讓 Laravel Queue 系統可以 retry
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ use Illuminate\Support\Facades\File;
|
||||
use WireUi\Traits\WireUiActions;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use App\Jobs\ImportArtistJob;
|
||||
use App\Jobs\ImportJob;
|
||||
|
||||
|
||||
class ArtistImportData extends Component
|
||||
@ -55,7 +55,7 @@ class ArtistImportData extends Component
|
||||
$path = $this->file->storeAs('imports', uniqid() . '_' . $this->file->getClientOriginalName());
|
||||
|
||||
// 丟到 queue 執行
|
||||
ImportArtistJob::dispatch($path);
|
||||
ImportJob::dispatch($path,'Artist');
|
||||
|
||||
$this->notification()->send([
|
||||
'icon' => 'info',
|
||||
|
@ -8,7 +8,7 @@ use Illuminate\Support\Facades\File;
|
||||
use WireUi\Traits\WireUiActions;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use App\Jobs\ImportSongJob;
|
||||
use App\Jobs\ImportJob;
|
||||
|
||||
|
||||
class SongImportData extends Component
|
||||
@ -55,7 +55,7 @@ class SongImportData extends Component
|
||||
$path = $this->file->storeAs('imports', uniqid() . '_' . $this->file->getClientOriginalName());
|
||||
|
||||
// 丟到 queue 執行
|
||||
ImportSongJob::dispatch($path);
|
||||
ImportJob::dispatch($path,'Song');
|
||||
|
||||
$this->notification()->send([
|
||||
'icon' => 'info',
|
||||
|
47
database/migrations/2025_04_24_031630_create_songs_table.php
Normal file
47
database/migrations/2025_04_24_031630_create_songs_table.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('song_library_cache', function (Blueprint $table) {
|
||||
$table->integer('song_id')->primary();
|
||||
$table->string('song_name', 255)->nullable();
|
||||
$table->string('artistA', 255)->nullable();
|
||||
$table->string('artistB', 255)->nullable();
|
||||
$table->string('song_filename', 255)->nullable();
|
||||
$table->string('artistA_simplified', 255)->nullable();
|
||||
$table->string('ArtistB_simplified', 255)->nullable();
|
||||
$table->string('artistA_category', 255)->nullable();
|
||||
$table->string('artistB_category', 255)->nullable();
|
||||
$table->string('song_simplified', 255)->nullable();
|
||||
$table->string('situations', 255)->nullable();
|
||||
$table->string('vocal', 255)->nullable();
|
||||
$table->string('language_name', 50)->nullable();
|
||||
$table->string('phonetic_abbr', 255)->nullable();
|
||||
$table->string('artistA_phonetic', 255)->nullable();
|
||||
$table->string('artistB_phonetic', 255)->nullable();
|
||||
$table->string('artistA_pinyin', 255)->nullable();
|
||||
$table->string('artistB_pinyin', 255)->nullable();
|
||||
$table->string('pinyin_abbr', 255)->nullable();
|
||||
$table->integer('song_counts')->nullable();
|
||||
$table->dateTime('add_date')->nullable();
|
||||
$table->dateTime('updated_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('song_library_cache');
|
||||
}
|
||||
};
|
BIN
storage/.DS_Store
vendored
BIN
storage/.DS_Store
vendored
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user