[RELEASE] 晉升 demo 到 main 正式上線商品軟刪除與圖片破圖優化
1. 於 DispenseRecord、OrderItem 及 MachineStockMovement 模型之 product 關聯中加入 withTrashed(),使軟刪除商品的歷史快照仍可正常讀取。
2. 將列表、側邊詳情面板與報表導出中的 product->name 統一修改為 product->localized_name ?? __('Unknown Product'),支援多語系切換與翻譯並更正為 '未知商品'。
3. 在銷售明細的商品圖片區塊整合 Alpine.js x-on:error 動態防呆,一旦破圖自動無縫退回 3D 箱子預設占位 SVG,解決與 Blade 內建 @error 衝突引起的編譯錯誤。
This commit is contained in:
commit
0f020afa6c
@ -833,7 +833,7 @@ class SalesController extends Controller
|
||||
$row = [
|
||||
$log->machine->name ?? 'Unknown',
|
||||
$log->machine->serial_no ?? '---',
|
||||
$log->product->name ?? 'Unknown Product',
|
||||
$log->product->localized_name ?? __('Unknown Product'),
|
||||
$log->slot_no,
|
||||
number_format($log->amount, 2, '.', ''),
|
||||
$statusLabel,
|
||||
|
||||
@ -76,7 +76,7 @@ class MachineStockMovement extends Model
|
||||
|
||||
public function product(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Product::class);
|
||||
return $this->belongsTo(Product::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function creator(): BelongsTo
|
||||
|
||||
@ -45,6 +45,6 @@ class DispenseRecord extends Model
|
||||
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(Product::class);
|
||||
return $this->belongsTo(Product::class)->withTrashed();
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +34,6 @@ class OrderItem extends Model
|
||||
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(Product::class);
|
||||
return $this->belongsTo(Product::class)->withTrashed();
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,15 +126,19 @@
|
||||
|
||||
<div class="space-y-3">
|
||||
@foreach($order->items as $item)
|
||||
<div class="luxury-card p-4 rounded-2xl flex items-center gap-4 group/item transition-all hover:border-cyan-500/30">
|
||||
<div class="w-16 h-16 rounded-xl bg-slate-100 dark:bg-slate-800 flex-shrink-0 overflow-hidden border border-slate-200 dark:border-slate-700 group-hover:scale-105 transition-transform flex items-center justify-center">
|
||||
<div class="luxury-card p-4 rounded-2xl flex items-center gap-4 group/item transition-all hover:border-cyan-500/30"
|
||||
x-data="{ imgFailed: {{ (isset($item->product->image_url) && $item->product->image_url) ? 'false' : 'true' }} }">
|
||||
<div class="w-16 h-16 rounded-xl bg-slate-100 dark:bg-slate-800 flex-shrink-0 overflow-hidden border border-slate-200 dark:border-slate-700 group-hover:scale-105 transition-transform flex items-center justify-center relative">
|
||||
@if(isset($item->product->image_url) && $item->product->image_url)
|
||||
<img src="{{ $item->product->image_url }}" class="w-full h-full object-cover">
|
||||
@else
|
||||
<svg class="w-8 h-8 text-slate-300 group-hover:text-cyan-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<img src="{{ $item->product->image_url }}" class="w-full h-full object-cover" x-show="!imgFailed" x-on:error="imgFailed = true">
|
||||
@endif
|
||||
|
||||
<div x-show="imgFailed"
|
||||
class="absolute inset-0 flex items-center justify-center bg-slate-50 dark:bg-slate-800/50">
|
||||
<svg class="w-8 h-8 text-slate-300 dark:text-slate-600 group-hover/item:text-cyan-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"/>
|
||||
</svg>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-base font-extrabold text-slate-800 dark:text-white truncate tracking-tight">{{ $item->product_name }}</p>
|
||||
@ -198,7 +202,7 @@
|
||||
<span class="text-xs font-black text-cyan-600 dark:text-cyan-400 font-mono">#{{ str_pad($dispense->slot_no, 2, '0', STR_PAD_LEFT) }}</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<p class="text-sm font-bold text-slate-700 dark:text-slate-200">{{ $dispense->product->name ?? __('Unknown') }}</p>
|
||||
<p class="text-sm font-bold text-slate-700 dark:text-slate-200">{{ $dispense->product->localized_name ?? __('Unknown Product') }}</p>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-right">
|
||||
@php
|
||||
|
||||
@ -188,7 +188,7 @@
|
||||
</td>
|
||||
<td class="px-6 py-6">
|
||||
<div class="text-sm font-black text-cyan-600 dark:text-cyan-400 mb-0.5">
|
||||
{{ $log->product->name ?? 'Unknown Product' }}
|
||||
{{ $log->product->localized_name ?? __('Unknown Product') }}
|
||||
</div>
|
||||
<div class="text-xs font-bold text-slate-400 uppercase tracking-widest">
|
||||
{{ __('Slot') }}: {{ $log->slot_no }}
|
||||
@ -287,7 +287,7 @@
|
||||
__('Product / Slot') }}</p>
|
||||
<div class="flex flex-col gap-0.5 min-w-0">
|
||||
<p class="text-sm font-black text-cyan-600 dark:text-cyan-400 truncate">
|
||||
{{ $log->product->name ?? 'Unknown' }}
|
||||
{{ $log->product->localized_name ?? __('Unknown Product') }}
|
||||
</p>
|
||||
<p class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">
|
||||
{{ __('Slot') }}: {{ $log->slot_no }}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user