[FEAT] 庫存清單與機台概覽顯示貨道鎖定狀態

1. 庫存與效期管理頁(列表/矩陣/手機卡片)商品旁顯示鎖定徽章,使用者可在清單直接辨識暫停販售貨道
2. 機台庫存概覽頁(格狀/表格/手機卡片)同步顯示鎖定徽章
3. 新增 Sale Paused 語系 key 三語系對齊(暫停販售 / Sale Paused / 販売停止)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sky121113 2026-06-24 14:49:59 +08:00
parent 6ce4c2c8ed
commit 1bd8971310
5 changed files with 56 additions and 11 deletions

View File

@ -1808,6 +1808,7 @@
"Running Status": "Running Status", "Running Status": "Running Status",
"SYSTEM": "SYSTEM", "SYSTEM": "SYSTEM",
"Safety Stock": "Safety Stock", "Safety Stock": "Safety Stock",
"Sale Paused": "Sale Paused",
"Sale Price": "Sale Price", "Sale Price": "Sale Price",
"Sale Status": "Sale Status", "Sale Status": "Sale Status",
"Sales": "Sales", "Sales": "Sales",

View File

@ -1808,6 +1808,7 @@
"Running Status": "稼働ステータス", "Running Status": "稼働ステータス",
"SYSTEM": "システムレベル", "SYSTEM": "システムレベル",
"Safety Stock": "安全在庫", "Safety Stock": "安全在庫",
"Sale Paused": "販売停止",
"Sale Price": "販売価格", "Sale Price": "販売価格",
"Sale Status": "販売状態", "Sale Status": "販売状態",
"Sales": "販売管理", "Sales": "販売管理",

View File

@ -1808,6 +1808,7 @@
"Running Status": "運行狀態", "Running Status": "運行狀態",
"SYSTEM": "系統層級", "SYSTEM": "系統層級",
"Safety Stock": "安全庫存", "Safety Stock": "安全庫存",
"Sale Paused": "暫停販售",
"Sale Price": "售價", "Sale Price": "售價",
"Sale Status": "銷售狀態", "Sale Status": "銷售狀態",
"Sales": "銷售管理", "Sales": "銷售管理",

View File

@ -710,12 +710,21 @@
class="text-xs font-black uppercase tracking-tighter text-slate-800 dark:text-white" class="text-xs font-black uppercase tracking-tighter text-slate-800 dark:text-white"
x-text="slot.slot_no"></span> x-text="slot.slot_no"></span>
</div> </div>
<template x-if="slot.max_stock > 0 && slot.stock <= (slot.max_stock * 0.2)"> <div class="flex items-center gap-1.5">
<div <template x-if="slot.is_locked">
class="px-2.5 py-1.5 rounded-xl bg-rose-500 text-white text-[9px] font-black uppercase tracking-widest shadow-lg shadow-rose-500/30 animate-pulse whitespace-nowrap select-none"> <div
{{ __('Low') }} class="flex items-center gap-1 px-2.5 py-1.5 rounded-xl bg-rose-500 text-white text-[9px] font-black uppercase tracking-widest shadow-lg shadow-rose-500/30 whitespace-nowrap select-none">
</div> <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
</template> {{ __('Sale Paused') }}
</div>
</template>
<template x-if="slot.max_stock > 0 && slot.stock <= (slot.max_stock * 0.2)">
<div
class="px-2.5 py-1.5 rounded-xl bg-rose-500 text-white text-[9px] font-black uppercase tracking-widest shadow-lg shadow-rose-500/30 animate-pulse whitespace-nowrap select-none">
{{ __('Low') }}
</div>
</template>
</div>
</div> </div>
<!-- Product Image --> <!-- Product Image -->
@ -821,8 +830,16 @@
</template> </template>
</div> </div>
<div> <div>
<div class="text-base font-black text-slate-800 dark:text-slate-200" <div class="flex items-center gap-2">
x-text="slot.product?.name || '{{ __('Empty Slot') }}'"></div> <span class="text-base font-black text-slate-800 dark:text-slate-200"
x-text="slot.product?.name || '{{ __('Empty Slot') }}'"></span>
<template x-if="slot.is_locked">
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-rose-500/10 text-rose-500 text-[10px] font-black uppercase tracking-wider whitespace-nowrap">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
{{ __('Locked (Sale Paused)') }}
</span>
</template>
</div>
<template x-if="slot.product?.id"> <template x-if="slot.product?.id">
<div class="mt-1"> <div class="mt-1">
<span class="text-xs font-bold text-slate-400 dark:text-slate-500 font-mono tracking-widest uppercase">{{ __('ID') }}: <span x-text="slot.product.id"></span></span> <span class="text-xs font-bold text-slate-400 dark:text-slate-500 font-mono tracking-widest uppercase">{{ __('ID') }}: <span x-text="slot.product.id"></span></span>
@ -887,7 +904,12 @@
</div> </div>
</div> </div>
<div class="shrink-0 text-right"> <div class="shrink-0 text-right">
<span class="text-xs font-black px-2.5 py-1.5 rounded-lg bg-slate-900/10 dark:bg-white/10" x-text="slot.slot_no"></span> <template x-if="slot.is_locked">
<span class="inline-flex items-center gap-1 text-[10px] font-black px-2.5 py-1.5 rounded-lg bg-rose-500/10 text-rose-500 uppercase tracking-wider whitespace-nowrap">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
{{ __('Sale Paused') }}
</span>
</template>
</div> </div>
</div> </div>

View File

@ -296,6 +296,12 @@
<span class="text-sm font-black tracking-tighter text-slate-800 dark:text-white" <span class="text-sm font-black tracking-tighter text-slate-800 dark:text-white"
x-text="slot.slot_no"></span> x-text="slot.slot_no"></span>
</div> </div>
<template x-if="slot.is_locked">
<div class="absolute top-4 right-5 flex items-center gap-1 px-2.5 py-1.5 rounded-xl bg-rose-500 text-white text-[9px] font-black uppercase tracking-widest shadow-lg shadow-rose-500/30 whitespace-nowrap select-none">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
{{ __('Sale Paused') }}
</div>
</template>
<div class="relative w-16 h-16 mb-4 mt-2"> <div class="relative w-16 h-16 mb-4 mt-2">
<div <div
@ -364,8 +370,16 @@
</template> </template>
</div> </div>
<div> <div>
<div class="text-base font-black text-slate-800 dark:text-slate-200" <div class="flex items-center gap-2">
x-text="slot.product?.name || '{{ __('Empty Slot') }}'"></div> <span class="text-base font-black text-slate-800 dark:text-slate-200"
x-text="slot.product?.name || '{{ __('Empty Slot') }}'"></span>
<template x-if="slot.is_locked">
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-rose-500/10 text-rose-500 text-[10px] font-black uppercase tracking-wider whitespace-nowrap">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
{{ __('Locked (Sale Paused)') }}
</span>
</template>
</div>
<div class="flex flex-wrap items-center gap-x-2.5 gap-y-1 mt-1"> <div class="flex flex-wrap items-center gap-x-2.5 gap-y-1 mt-1">
<template x-if="slot.product?.id"> <template x-if="slot.product?.id">
<span class="text-xs font-bold text-slate-400 dark:text-slate-500 font-mono tracking-widest uppercase">{{ __('ID') }}: <span x-text="slot.product.id"></span></span> <span class="text-xs font-bold text-slate-400 dark:text-slate-500 font-mono tracking-widest uppercase">{{ __('ID') }}: <span x-text="slot.product.id"></span></span>
@ -435,6 +449,12 @@
</div> </div>
<div class="shrink-0 text-right"> <div class="shrink-0 text-right">
<p class="text-base font-black text-emerald-500" x-text="'$' + Math.floor(slot.product?.price || 0)"></p> <p class="text-base font-black text-emerald-500" x-text="'$' + Math.floor(slot.product?.price || 0)"></p>
<template x-if="slot.is_locked">
<span class="inline-flex items-center gap-1 mt-1 text-[10px] font-black px-2 py-0.5 rounded-md bg-rose-500/10 text-rose-500 uppercase tracking-wider whitespace-nowrap">
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>
{{ __('Sale Paused') }}
</span>
</template>
</div> </div>
</div> </div>