diff --git a/frontend/src/composables/useKitCost.js b/frontend/src/composables/useKitCost.js index adfc194..3ddf351 100644 --- a/frontend/src/composables/useKitCost.js +++ b/frontend/src/composables/useKitCost.js @@ -35,12 +35,14 @@ export function useKitCost() { } if (totalBottlePrice === 0) return {} - // Proportional allocation + // Proportional allocation — kit accessories treated as freebies, + // so oil cost = min(kit price, sum of bottle prices) + const effectivePrice = Math.min(kit.price, totalBottlePrice) const perDrop = {} for (const name of resolved) { const meta = oils.oilsMeta[name] const bp = oilBottlePrices[name] - const kitCostForOil = (bp / totalBottlePrice) * kit.price + const kitCostForOil = (bp / totalBottlePrice) * effectivePrice const drops = meta ? meta.dropCount : 1 perDrop[name] = drops > 0 ? kitCostForOil / drops : 0 } @@ -124,6 +126,7 @@ export function useKitCost() { id, name: recipe.name, tags: recipe.tags, + volume: recipe.volume, ingredients: recipe.ingredients, originalCost: recipe.originalCost, costs, diff --git a/frontend/src/views/KitExport.vue b/frontend/src/views/KitExport.vue index e65b0f1..9aebec9 100644 --- a/frontend/src/views/KitExport.vue +++ b/frontend/src/views/KitExport.vue @@ -39,6 +39,7 @@ 配方名 + 可做次数 套装成本 原价成本 售价 @@ -47,7 +48,8 @@ - {{ r.name }} + {{ r.name }} {{ r.volume || '单次' }} + {{ calcMaxTimes(r) }} {{ fmtPrice(r.kitCost) }} {{ fmtPrice(r.originalCost) }} @@ -83,7 +85,7 @@ - {{ row.name }} + {{ row.name }} {{ row.volume || '单次' }} @@ -142,6 +144,20 @@ function saveSellingPrices() { localStorage.setItem(STORAGE_KEY, JSON.stringify(sellingPrices.value)) } +// Calculate how many times a recipe can be made with the kit (limited by the oil that runs out first) +function calcMaxTimes(recipe) { + const ings = (recipe.ingredients || []).filter(i => i.oil && i.oil !== '椰子油' && i.drops > 0) + if (!ings.length) return '—' + let minTimes = Infinity + for (const ing of ings) { + const meta = oils.oilsMeta[ing.oil] + if (!meta || !meta.dropCount) return '—' + const times = Math.floor(meta.dropCount / ing.drops) + if (times < minTimes) minTimes = times + } + return minTimes === Infinity ? '—' : minTimes + '次' +} + function getSellingPrice(recipeId) { return sellingPrices.value[recipeId] ?? 0 } @@ -394,6 +410,8 @@ async function exportExcel(mode) { .td-cost.original { color: #999; font-weight: 400; } .td-profit { font-weight: 600; color: #4a9d7e; } .td-profit.negative { color: #ef5350; } +.td-volume { font-size: 10px; color: #b0aab5; margin-left: 4px; } +.td-times { color: #6b6375; font-size: 12px; } .td-kit-available { font-weight: 500; color: #4a9d7e; background: #f0faf5; } .td-kit-na { background: #fafafa; } .na { color: #ddd; }