feat: 標準化全系統數值輸入欄位與擴充商品價格功能
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Has been skipped
Koori-ERP-Deploy-System / deploy-production (push) Successful in 1m0s

1. UI 標準化:
   - 針對全系統數值輸入欄位統一加上 step='any' 以支援小數點。
   - 表格形式 (Table) 的數值輸入欄位統一加上 text-right 靠右對齊。
   - 修正 Components 與 Pages 中所有涉及金額與數量的輸入框。

2. 功能擴充與修正:
   - 擴充 Product 模型與相關 Dialog 以支援多種價格設定。
   - 修正 Inventory/GoodsReceipt/Create.tsx 未使用的變數錯誤。
   - 優化庫存相關頁面的 UI 一致性。

3. 其他:
   - 更新相關的 Type 定義與 Controller 邏輯。
This commit is contained in:
2026-02-05 11:45:08 +08:00
parent 04f3891275
commit 3ce96537b3
40 changed files with 774 additions and 212 deletions

View File

@@ -47,6 +47,10 @@ export default function ProductDialog({
conversion_rate: "",
purchase_unit_id: "",
location: "",
cost_price: "",
price: "",
member_price: "",
wholesale_price: "",
});
useEffect(() => {
@@ -65,6 +69,10 @@ export default function ProductDialog({
conversion_rate: product.conversionRate ? product.conversionRate.toString() : "",
purchase_unit_id: product.purchaseUnitId?.toString() || "",
location: product.location || "",
cost_price: product.cost_price?.toString() || "",
price: product.price?.toString() || "",
member_price: product.member_price?.toString() || "",
wholesale_price: product.wholesale_price?.toString() || "",
});
} else {
reset();
@@ -235,6 +243,72 @@ export default function ProductDialog({
</div>
</div>
{/* 價格設定區塊 */}
<div className="space-y-4">
<h3 className="text-lg font-medium border-b pb-2"></h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="cost_price"></Label>
<Input
id="cost_price"
type="number"
min="0"
step="any"
value={data.cost_price}
onChange={(e) => setData("cost_price", e.target.value)}
placeholder="0"
className={errors.cost_price ? "border-red-500" : ""}
/>
{errors.cost_price && <p className="text-sm text-red-500">{errors.cost_price}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="price"></Label>
<Input
id="price"
type="number"
min="0"
step="any"
value={data.price}
onChange={(e) => setData("price", e.target.value)}
placeholder="0"
className={errors.price ? "border-red-500" : ""}
/>
{errors.price && <p className="text-sm text-red-500">{errors.price}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="member_price"></Label>
<Input
id="member_price"
type="number"
min="0"
step="any"
value={data.member_price}
onChange={(e) => setData("member_price", e.target.value)}
placeholder="0"
className={errors.member_price ? "border-red-500" : ""}
/>
{errors.member_price && <p className="text-sm text-red-500">{errors.member_price}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="wholesale_price"></Label>
<Input
id="wholesale_price"
type="number"
min="0"
step="any"
value={data.wholesale_price}
onChange={(e) => setData("wholesale_price", e.target.value)}
placeholder="0"
className={errors.wholesale_price ? "border-red-500" : ""}
/>
{errors.wholesale_price && <p className="text-sm text-red-500">{errors.wholesale_price}</p>}
</div>
</div>
</div>
{/* 單位設定區塊 */}
<div className="space-y-4">
<h3 className="text-lg font-medium border-b pb-2"></h3>
@@ -278,7 +352,7 @@ export default function ProductDialog({
<Input
id="conversion_rate"
type="number"
step="0.0001"
step="any"
value={data.conversion_rate}
onChange={(e) => setData("conversion_rate", e.target.value)}
placeholder={data.large_unit_id && data.base_unit_id ? `1 ${units.find(u => u.id.toString() === data.large_unit_id)?.name} = ? ${units.find(u => u.id.toString() === data.base_unit_id)?.name}` : ""}