diff --git a/frontend/src/components/RecipeCard.vue b/frontend/src/components/RecipeCard.vue index 2d633e7..7606d35 100644 --- a/frontend/src/components/RecipeCard.vue +++ b/frontend/src/components/RecipeCard.vue @@ -56,13 +56,10 @@ const volumeLabel = computed(() => { if (ml <= 2) return '单次' return `${Math.round(ml)}ml` } - // Non-coconut: check if has portion product, extract volume from note - const hasPortion = ings.some(i => oilsStore.isPortionUnit(i.oil)) - if (hasPortion) { - const note = props.recipe.note || '' - const m = note.match(/(\d+)\s*(ml|毫升|克|g)/i) - if (m) return `${m[1]}${m[2].toLowerCase()}` - return '调配' + // Non-coconut: find portion product and show its amount + unit + const portionIng = ings.find(i => oilsStore.isPortionUnit(i.oil)) + if (portionIng) { + return `${portionIng.drops}${oilsStore.unitLabel(portionIng.oil)}` } return '' }) diff --git a/frontend/src/stores/oils.js b/frontend/src/stores/oils.js index 234573f..256b5fe 100644 --- a/frontend/src/stores/oils.js +++ b/frontend/src/stores/oils.js @@ -77,14 +77,16 @@ export const useOilsStore = defineStore('oils', () => { oilsMeta.value = newMeta } - async function saveOil(name, bottlePrice, dropCount, retailPrice, enName = null) { - await api.post('/api/oils', { + async function saveOil(name, bottlePrice, dropCount, retailPrice, enName = null, unit = null) { + const payload = { name, bottle_price: bottlePrice, drop_count: dropCount, retail_price: retailPrice, en_name: enName, - }) + } + if (unit) payload.unit = unit + await api.post('/api/oils', payload) await loadOils() } diff --git a/frontend/src/views/OilReference.vue b/frontend/src/views/OilReference.vue index 4123a5f..ced2b89 100644 --- a/frontend/src/views/OilReference.vue +++ b/frontend/src/views/OilReference.vue @@ -107,7 +107,12 @@
-
+
+ + +
+ +
@@ -124,6 +129,20 @@
+ +
+ + + + + + + +
@@ -413,12 +432,15 @@ const activeCardName = ref(null) const activeCard = ref(null) // Add oil form +const addType = ref('oil') const newOilName = ref('') const newOilEnName = ref('') const newBottlePrice = ref(null) const newVolume = ref('5') const newCustomDrops = ref(null) const newRetailPrice = ref(null) +const newProductAmount = ref(null) +const newProductUnit = ref('ml') // Edit oil const editingOilName = ref(null) @@ -657,6 +679,29 @@ async function addOil() { } } +async function addProduct() { + if (!newOilName.value.trim() || !newProductAmount.value) return + try { + await oils.saveOil( + newOilName.value.trim(), + newBottlePrice.value || 0, + newProductAmount.value, + newRetailPrice.value || null, + newOilEnName.value.trim() || null, + newProductUnit.value + ) + ui.showToast(`已添加: ${newOilName.value}`) + newOilName.value = '' + newOilEnName.value = '' + newBottlePrice.value = null + newProductAmount.value = null + newProductUnit.value = 'ml' + newRetailPrice.value = null + } catch (e) { + ui.showToast('添加失败: ' + (e.message || '')) + } +} + function editOil(name) { editingOilName.value = name editOilDisplayName.value = name @@ -1065,6 +1110,16 @@ async function saveCardImage(name) { } /* ===== Add Oil Form ===== */ +.add-type-tabs { display: flex; gap: 0; margin-bottom: 10px; } +.add-type-tab { + flex: 1; padding: 6px 0; text-align: center; font-size: 13px; cursor: pointer; + border: 1.5px solid var(--border, #d4cfc7); background: #fff; color: var(--text-mid, #6b6375); + font-family: inherit; +} +.add-type-tab:first-child { border-radius: 8px 0 0 8px; } +.add-type-tab:last-child { border-radius: 0 8px 8px 0; border-left: none; } +.add-type-tab.active { background: var(--sage, #7a9e7e); color: #fff; border-color: var(--sage, #7a9e7e); } + .add-oil-form { margin-bottom: 16px; padding: 14px;