[FEAT] 實作維修管理模組與 RBAC 權限整合、多語系支援及 UI 優化
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 1m3s

This commit is contained in:
2026-03-25 14:25:42 +08:00
parent 3d24ddff5a
commit 37ef6f1c10
23 changed files with 1446 additions and 460 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin\BasicSettings;
use App\Http\Controllers\Controller;
use App\Models\Machine\Machine;
use App\Traits\ImageHandler;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
@@ -11,6 +12,8 @@ use Illuminate\Support\Facades\Storage;
class MachinePhotoController extends Controller
{
use ImageHandler;
/**
* 更新機台照片
*/
@@ -64,50 +67,4 @@ class MachinePhotoController extends Controller
return back()->with('error', __('Failed to update machine images: ') . $e->getMessage());
}
}
/**
* 將圖片轉換為 WebP 並儲存
*/
protected function storeAsWebp($file, $directory): string
{
$extension = $file->getClientOriginalExtension();
$filename = uniqid() . '.webp';
$path = "{$directory}/{$filename}";
// 讀取原始圖片
$imageType = exif_imagetype($file->getRealPath());
switch ($imageType) {
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($file->getRealPath());
break;
case IMAGETYPE_PNG:
$source = imagecreatefrompng($file->getRealPath());
break;
case IMAGETYPE_WEBP:
$source = imagecreatefromwebp($file->getRealPath());
break;
default:
// 如果格式不支援,直接存
return $file->storeAs($directory, $file->hashName(), 'public');
}
if (!$source) {
return $file->storeAs($directory, $file->hashName(), 'public');
}
// 確保支援真彩色(解決 palette image 問題)
if (!imageistruecolor($source)) {
imagepalettetotruecolor($source);
}
// 捕捉輸出
ob_start();
imagewebp($source, null, 80);
$content = ob_get_clean();
imagedestroy($source);
Storage::disk('public')->put($path, $content);
return $path;
}
}

View File

@@ -6,6 +6,7 @@ use App\Http\Controllers\Admin\AdminController;
use App\Models\Machine\Machine;
use App\Models\Machine\MachineModel;
use App\Models\System\PaymentConfig;
use App\Traits\ImageHandler;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
@@ -16,6 +17,8 @@ use Illuminate\Support\Facades\Log;
class MachineSettingController extends AdminController
{
use ImageHandler;
/**
* 顯示機台與型號設定列表 (採用標籤頁整合)
*/
@@ -75,7 +78,7 @@ class MachineSettingController extends AdminController
$imagePaths = [];
if ($request->hasFile('images')) {
foreach (array_slice($request->file('images'), 0, 3) as $image) {
$imagePaths[] = $this->processAndStoreImage($image);
$imagePaths[] = $this->storeAsWebp($image, 'machines');
}
}
@@ -171,7 +174,7 @@ class MachineSettingController extends AdminController
}
// 處理並儲存新圖
$currentImages[$index] = $this->processAndStoreImage($file);
$currentImages[$index] = $this->storeAsWebp($file, 'machines');
$updated = true;
}
@@ -184,49 +187,4 @@ class MachineSettingController extends AdminController
return redirect()->route('admin.basic-settings.machines.index')
->with('success', __('Machine settings updated successfully.'));
}
/**
* 處理並儲存圖片 (轉換為 WebP 並調整大小)
*/
protected function processAndStoreImage($file)
{
$path = 'machines/' . \Illuminate\Support\Str::random(40) . '.webp';
// 載入原圖
$imageInfo = getimagesize($file->getRealPath());
$mime = $imageInfo['mime'];
switch ($mime) {
case 'image/jpeg':
$image = imagecreatefromjpeg($file->getRealPath());
break;
case 'image/png':
$image = imagecreatefrompng($file->getRealPath());
break;
case 'image/gif':
$image = imagecreatefromgif($file->getRealPath());
break;
default:
return $file->store('machines', 'public');
}
if ($image) {
// [修正] imagewebp(): Palette image not supported by webp
// 若為 Palette 圖片 (例如 GIF),轉換為 Truecolor
if (!imageistruecolor($image)) {
imagepalettetotruecolor($image);
}
\Illuminate\Support\Facades\Storage::disk('public')->makeDirectory('machines');
$fullPath = \Illuminate\Support\Facades\Storage::disk('public')->path($path);
// 轉換並儲存 (品質 80)
imagewebp($image, $fullPath, 80);
imagedestroy($image);
return $path;
}
return $file->store('machines', 'public');
}
}