滙入大量歌手會有問題 修正 20250506
This commit is contained in:
parent
0821b16ac6
commit
e748b7ff3d
BIN
app/.DS_Store
vendored
Normal file
BIN
app/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
app/Enums/.DS_Store
vendored
Normal file
BIN
app/Enums/.DS_Store
vendored
Normal file
Binary file not shown.
@ -4,44 +4,69 @@ namespace App\Imports;
|
||||
|
||||
use App\Models\Artist;
|
||||
use App\Enums\ArtistCategory;
|
||||
use Maatwebsite\Excel\Concerns\ToModel;
|
||||
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 ToModel, WithHeadingRow
|
||||
class ArtistDataImport implements ToCollection, WithHeadingRow, WithChunkReading, WithBatchInserts
|
||||
{
|
||||
public int $successCount = 0;
|
||||
public int $failCount = 0;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 關閉 heading row 格式化
|
||||
HeadingRowFormatter::default('none');
|
||||
}
|
||||
|
||||
public function model(array $row)
|
||||
public function collection(Collection $rows)
|
||||
{
|
||||
$name = trim($row['名稱'] ?? '');
|
||||
$category = trim($row['類別'] ?? '未定義');
|
||||
$enable = trim($row['狀態'] ?? 1);
|
||||
if (empty($name)) {
|
||||
$this->failCount++;
|
||||
return null;
|
||||
}
|
||||
$toInsert = [];
|
||||
|
||||
try {
|
||||
Artist::firstOrCreate(
|
||||
['name' => $name],
|
||||
['category' => ArtistCategory::tryFrom($category) ?? ArtistCategory::Unset],
|
||||
['enable' => $enable],
|
||||
);
|
||||
$this->successCount++;
|
||||
} catch (\Throwable $e) {
|
||||
$this->failCount++;
|
||||
foreach ($rows as $row) {
|
||||
$name=trim($row['歌手姓名'] ?? '');
|
||||
if (empty($name)) continue;
|
||||
|
||||
// 字元處理
|
||||
$simplified = ChineseNameConverter::convertToSimplified($name);
|
||||
if (!array_key_exists('歌手注音', $row)) {
|
||||
$phoneticAbbr = ChineseNameConverter::getKTVZhuyinAbbr($simplified);
|
||||
} else {
|
||||
$phoneticAbbr = trim($row['歌手注音']);
|
||||
}
|
||||
$pinyinAbbr = ChineseNameConverter::getKTVPinyinAbbr($simplified);
|
||||
if (!array_key_exists('歌手注音', $row)) {
|
||||
$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 資料
|
||||
$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)
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
Artist::insert($toInsert);
|
||||
}
|
||||
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
public function batchSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
public function headingRow(): int
|
||||
{
|
||||
return 1;
|
||||
|
42
app/Jobs/ImportArtistJob.php
Normal file
42
app/Jobs/ImportArtistJob.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?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
|
||||
{
|
||||
Excel::import(new ArtistDataImport, $this->filePath);
|
||||
// 匯入完成後刪除檔案
|
||||
if (Storage::exists($this->filePath)) {
|
||||
Storage::delete($this->filePath);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@ namespace App\Livewire\Admin;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Imports\ArtistDataImport;
|
||||
use App\Jobs\ImportArtistJob;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ArtistImportData extends Component
|
||||
{
|
||||
@ -41,13 +41,15 @@ class ArtistImportData extends Component
|
||||
'file' => 'required|file|mimes:csv,xlsx,xls'
|
||||
]);
|
||||
if ($this->canCreate) {
|
||||
$import = new ArtistDataImport();
|
||||
Excel::import($import, $this->file);
|
||||
$success = $import->successCount;
|
||||
$fail = $import->failCount;
|
||||
// 儲存檔案至 storage
|
||||
$path = $this->file->storeAs('imports', uniqid() . '_' . $this->file->getClientOriginalName());
|
||||
|
||||
// 丟到 queue 執行
|
||||
ImportArtistJob::dispatch($path);
|
||||
|
||||
$this->reset('file');
|
||||
$this->showModal =false;
|
||||
session()->flash('message', '匯入完成:成功 $success 筆,失敗 $fail 筆。');
|
||||
$this->showModal = false;
|
||||
session()->flash('message', '已排入背景匯入作業,請稍候查看結果');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,33 +3,48 @@
|
||||
{{-- 說明區塊 --}}
|
||||
<div class="mb-4 p-4 bg-gray-100 border border-gray-300 rounded text-sm text-gray-700">
|
||||
<p class="font-semibold mb-2">匯入格式說明</p>
|
||||
<p class="mb-2">請依下列表格格式準備 CSV 檔案:</p>
|
||||
<p class="mb-2">請依下列表格格式準備 Excel 或 CSV 檔案:</p>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-sm text-left border border-collapse border-gray-300 mb-2">
|
||||
<div class="overflow-x-auto mb-2">
|
||||
<table class="min-w-full text-sm text-left border border-collapse border-gray-300">
|
||||
<thead class="bg-gray-200">
|
||||
<tr>
|
||||
<th class="border border-gray-300 px-3 py-1">類別</th>
|
||||
<th class="border border-gray-300 px-3 py-1">名稱</th>
|
||||
<th class="border border-gray-300 px-3 py-1">欄位名稱</th>
|
||||
<th class="border border-gray-300 px-3 py-1">說明</th>
|
||||
<th class="border border-gray-300 px-3 py-1">範例</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-1">男</td>
|
||||
<td class="border border-gray-300 px-3 py-1">某男</td>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手姓名</td>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手姓名唯一</td>
|
||||
<td class="border border-gray-300 px-3 py-1">田馥甄</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手注音</td>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手注音第一字碼</td>
|
||||
<td class="border border-gray-300 px-3 py-1">ㄊㄈㄓ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手分類</td>
|
||||
<td class="border border-gray-300 px-3 py-1">男、女、團、外、其他</td>
|
||||
<td class="border border-gray-300 px-3 py-1">女</td>
|
||||
<td class="border border-gray-300 px-3 py-1">某女</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-1">狀態</td>
|
||||
<td class="border border-gray-300 px-3 py-1">是否啟用(1:啟用,0:停用)</td>
|
||||
<td class="border border-gray-300 px-3 py-1">1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-1">歌手筆畫</td>
|
||||
<td class="border border-gray-300 px-3 py-1">字首筆劃</td>
|
||||
<td class="border border-gray-300 px-3 py-1">5</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-600 text-xs">
|
||||
※ 類別欄位僅可使用:<strong>男</strong>、<strong>女</strong>、<strong>團</strong>、<strong>外</strong>、<strong>其他</strong>。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
{{-- 檔案上傳 --}}
|
||||
<input type="file" wire:model="file" accept=".csv, .xls, .xlsx" class="mb-4 w-full" />
|
||||
|
13
開發手冊.ini
13
開發手冊.ini
@ -82,6 +82,13 @@ php artisan make:livewire Admin/ArtistForm
|
||||
php artisan make:livewire Admin/SongForm
|
||||
|
||||
|
||||
php artisan make:model Branches -m
|
||||
php artisan make:model Rooms -m
|
||||
php artisan make:model RoomStatusLogs -m
|
||||
php artisan make:model OperationLog -m
|
||||
|
||||
php artisan make:observer GenericObserver --model=OperationLog
|
||||
|
||||
php artisan make:model Branch -m
|
||||
php artisan make:model Room -m
|
||||
php artisan make:model RoomStatusLog -m
|
||||
|
||||
php artisan make:observer RoomObserver --model=Room
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user