diff --git a/frontend/src/views/OilReference.vue b/frontend/src/views/OilReference.vue index fb60fe2..aec177d 100644 --- a/frontend/src/views/OilReference.vue +++ b/frontend/src/views/OilReference.vue @@ -36,9 +36,11 @@
💡 稀释比例 = 1滴精油 : N滴椰子油
比例越大越温和,新手建议从高稀释比例开始
+
+ +
- @@ -75,9 +77,11 @@ 💧
少量多次,多喝水
使用精油后多补充水分,帮助身体代谢
+
+ +
- @@ -203,9 +207,11 @@

⚠️ 注意事项

{{ activeCard.caution }}

+
+ +
- @@ -546,12 +552,18 @@ function parseMethodBadges(methodStr) { } // Actions -function openOilDetail(name) { +async function openOilDetail(name) { const card = getOilCard(name) if (card) { activeCardName.value = name activeCard.value = card selectedOilName.value = null + // Pre-generate card image for instant save + oilCardImageUrl.value = null + await nextTick() + await new Promise(r => setTimeout(r, 300)) + const el = document.querySelector('.oil-card-modal') + if (el) await generateImageFromRef({ value: el }, oilCardImageUrl) } else { activeCard.value = null activeCardName.value = null @@ -748,33 +760,59 @@ async function generateImageFromRef(elRef, imageUrlRef) { } } -async function saveGeneratedImage(imageUrlRef, elRef, name) { - // Generate if not already done - if (!imageUrlRef.value) { - await generateImageFromRef(elRef, imageUrlRef) +// When modal opens, pre-generate the image (so save button has instant dataUrl) +watch(showDilution, async (v) => { + if (v) { + dilutionImageUrl.value = null + await nextTick() + await new Promise(r => setTimeout(r, 300)) + await generateImageFromRef(dilutionCardRef, dilutionImageUrl) } - if (!imageUrlRef.value) { - ui.showToast('图片生成失败') +}) +watch(showContra, async (v) => { + if (v) { + contraImageUrl.value = null + await nextTick() + await new Promise(r => setTimeout(r, 300)) + await generateImageFromRef(contraCardRef, contraImageUrl) + } +}) + +// Save: dataUrl is already cached, navigator.share runs in fresh user gesture +async function saveDilutionImage() { + if (!dilutionImageUrl.value) { + ui.showToast('图片生成中,请稍后再试') return } - // Same as RecipeDetailOverlay.saveImage const { saveImageFromUrl } = await import('../composables/useSaveImage') - await saveImageFromUrl(imageUrlRef.value, name) + await saveImageFromUrl(dilutionImageUrl.value, '精油稀释比例指南') ui.showToast('已保存图片') } -function saveDilutionImage() { - saveGeneratedImage(dilutionImageUrl, dilutionCardRef, '精油稀释比例指南') +async function saveContraImage() { + if (!contraImageUrl.value) { + ui.showToast('图片生成中,请稍后再试') + return + } + const { saveImageFromUrl } = await import('../composables/useSaveImage') + await saveImageFromUrl(contraImageUrl.value, '精油使用禁忌') + ui.showToast('已保存图片') } -function saveContraImage() { - saveGeneratedImage(contraImageUrl, contraCardRef, '精油使用禁忌') -} -function saveCardImage(name) { + +async function saveCardImage(name) { + // Oil card: generate on demand since we don't know which card opens const el = document.querySelector('.oil-card-modal') if (!el) { ui.showToast('找不到卡片'); return } - // Use a temporary ref-like object - const tmpRef = { value: el } - saveGeneratedImage(oilCardImageUrl, tmpRef, name + '_精油知识卡') + if (!oilCardImageUrl.value) { + await generateImageFromRef({ value: el }, oilCardImageUrl) + } + if (!oilCardImageUrl.value) { + ui.showToast('图片生成失败') + return + } + const { saveImageFromUrl } = await import('../composables/useSaveImage') + await saveImageFromUrl(oilCardImageUrl.value, name + '_精油知识卡') + ui.showToast('已保存图片') }