fix: 卡片预览加入容量切换,非单次滴数四舍五入
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 3s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
Some checks failed
PR Preview / teardown-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 5s
Test / build-check (push) Successful in 3s
PR Preview / test (pull_request) Successful in 4s
PR Preview / deploy-preview (pull_request) Successful in 12s
Test / e2e-test (push) Has been cancelled
- VOLUME_DROPS 新增「单次」(null,不缩放) - 新增 scaleIngredients() 按比例缩放成分 - 卡片预览区加入容量切换按钮,切换后实时更新滴数与成本 - priceInfo 与 coconutDrops 均基于缩放后数据 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,17 @@
|
|||||||
>English</button>
|
>English</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Volume selector -->
|
||||||
|
<div class="volume-controls card-volume-controls">
|
||||||
|
<button
|
||||||
|
v-for="(drops, ml) in VOLUME_DROPS"
|
||||||
|
:key="ml"
|
||||||
|
class="volume-btn"
|
||||||
|
:class="{ active: selectedCardVolume === ml }"
|
||||||
|
@click="onCardVolumeChange(ml)"
|
||||||
|
>{{ ml === '单次' ? '单次' : ml + 'ml' }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- QR / brand upload hint -->
|
<!-- QR / brand upload hint -->
|
||||||
<div v-if="showBrandHint" class="brand-upload-hint">
|
<div v-if="showBrandHint" class="brand-upload-hint">
|
||||||
<span class="hint-icon">✨</span>
|
<span class="hint-icon">✨</span>
|
||||||
@@ -382,6 +393,7 @@ const viewMode = ref('card')
|
|||||||
const cardRef = ref(null)
|
const cardRef = ref(null)
|
||||||
const cardImageUrl = ref(null)
|
const cardImageUrl = ref(null)
|
||||||
const cardLang = ref('zh')
|
const cardLang = ref('zh')
|
||||||
|
const selectedCardVolume = ref('单次')
|
||||||
const showTranslationEditor = ref(false)
|
const showTranslationEditor = ref(false)
|
||||||
const customRecipeNameEn = ref('')
|
const customRecipeNameEn = ref('')
|
||||||
const customOilNameEn = ref({})
|
const customOilNameEn = ref({})
|
||||||
@@ -400,14 +412,30 @@ const canEditThisRecipe = computed(() => {
|
|||||||
|
|
||||||
const isFav = computed(() => recipesStore.isFavorite(recipe.value))
|
const isFav = computed(() => recipesStore.isFavorite(recipe.value))
|
||||||
|
|
||||||
// Card ingredients: exclude coconut oil
|
// Scale ingredients proportionally to target volume; '单次' = no scaling
|
||||||
const cardIngredients = computed(() =>
|
function scaleIngredients(ingredients, volume) {
|
||||||
recipe.value.ingredients.filter(ing => ing.oil !== '椰子油')
|
const targetDrops = VOLUME_DROPS[volume]
|
||||||
|
if (!targetDrops) return ingredients // 单次:不缩放
|
||||||
|
const totalDrops = ingredients.reduce((sum, ing) => sum + (ing.drops || 0), 0)
|
||||||
|
if (totalDrops === 0) return ingredients
|
||||||
|
return ingredients.map(ing => ({
|
||||||
|
...ing,
|
||||||
|
drops: Math.round(ing.drops * targetDrops / totalDrops),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Card ingredients: scaled to selected volume, coconut oil excluded from display
|
||||||
|
const scaledCardIngredients = computed(() =>
|
||||||
|
scaleIngredients(recipe.value.ingredients, selectedCardVolume.value)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Coconut oil drops
|
const cardIngredients = computed(() =>
|
||||||
|
scaledCardIngredients.value.filter(ing => ing.oil !== '椰子油')
|
||||||
|
)
|
||||||
|
|
||||||
|
// Coconut oil drops (from scaled set)
|
||||||
const coconutDrops = computed(() => {
|
const coconutDrops = computed(() => {
|
||||||
const coco = recipe.value.ingredients.find(ing => ing.oil === '椰子油')
|
const coco = scaledCardIngredients.value.find(ing => ing.oil === '椰子油')
|
||||||
return coco ? coco.drops : 0
|
return coco ? coco.drops : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -433,7 +461,7 @@ const dilutionDesc = computed(() => {
|
|||||||
: `该配方适用于单次用量(共${totalDrops}滴),其中纯精油 ${totalEoDrops.value} 滴,椰子油 ${coconutDrops.value} 滴,稀释比例为 1:${ratio}`
|
: `该配方适用于单次用量(共${totalDrops}滴),其中纯精油 ${totalEoDrops.value} 滴,椰子油 ${coconutDrops.value} 滴,稀释比例为 1:${ratio}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const priceInfo = computed(() => oilsStore.fmtCostWithRetail(recipe.value.ingredients))
|
const priceInfo = computed(() => oilsStore.fmtCostWithRetail(scaledCardIngredients.value))
|
||||||
|
|
||||||
// Today string
|
// Today string
|
||||||
const todayStr = computed(() => {
|
const todayStr = computed(() => {
|
||||||
@@ -512,6 +540,12 @@ function switchLang(lang) {
|
|||||||
nextTick(() => generateCardImage())
|
nextTick(() => generateCardImage())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCardVolumeChange(ml) {
|
||||||
|
selectedCardVolume.value = ml
|
||||||
|
cardImageUrl.value = null
|
||||||
|
nextTick(() => generateCardImage())
|
||||||
|
}
|
||||||
|
|
||||||
async function saveImage() {
|
async function saveImage() {
|
||||||
if (!cardImageUrl.value) {
|
if (!cardImageUrl.value) {
|
||||||
await generateCardImage()
|
await generateCardImage()
|
||||||
@@ -1469,6 +1503,10 @@ async function saveRecipe() {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-volume-controls {
|
||||||
|
margin: 8px 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.volume-btn {
|
.volume-btn {
|
||||||
padding: 7px 16px;
|
padding: 7px 16px;
|
||||||
border: 1.5px solid var(--border, #e0d4c0);
|
border: 1.5px solid var(--border, #e0d4c0);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { api } from '../composables/useApi'
|
|||||||
export const DROPS_PER_ML = 18.6
|
export const DROPS_PER_ML = 18.6
|
||||||
|
|
||||||
export const VOLUME_DROPS = {
|
export const VOLUME_DROPS = {
|
||||||
|
'单次': null,
|
||||||
'2.5': 46,
|
'2.5': 46,
|
||||||
'5': 93,
|
'5': 93,
|
||||||
'10': 186,
|
'10': 186,
|
||||||
|
|||||||
Reference in New Issue
Block a user