KTV/app/Jobs/ImportSongChunkJob.php
2025-05-10 09:00:14 +08:00

140 lines
4.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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 = [];
protected array $artistCache =[];
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' => $this->formatText($row['歌名']),
'adddate' => $this->parseExcelDate($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()
]);
}
}
}
private 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;
}
protected function formatText($value)
{
if (is_numeric($value) && $value < 1 && $value > 0) {
// 嘗試判斷為時間類型的小數,轉為時間字串
$time = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);
return $time->format('H:i');
}
return trim((string) $value);
}
private function parseExcelDate($value): ?string
{
if (is_numeric($value)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', '1900-01-01')
->addDays((int)$value - 2)
->format('Y-m-d');
}
try {
return \Carbon\Carbon::parse($value)->format('Y-m-d');
} catch (\Exception $e) {
return null;
}
}
}