rewrite: 精油价目页保存图片逻辑完全照搬配方卡片
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 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 15s
Test / e2e-test (push) Failing after 53s
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 4s
PR Preview / test (pull_request) Successful in 5s
PR Preview / deploy-preview (pull_request) Successful in 15s
Test / e2e-test (push) Failing after 53s
完全复制 RecipeDetailOverlay 的模式:
1. import html2canvas at top level (not dynamic)
2. ref 存预生成的 imageUrl (dilutionImageUrl, contraImageUrl, oilCardImageUrl)
3. generateImageFromRef: html2canvas截图→dataUrl存入ref
参数: backgroundColor=null, scale=3, useCORS=true, allowTaint=false
4. saveGeneratedImage: 如果没截图先生成,然后调 saveImageFromUrl
5. saveImageFromUrl: navigator.share({files}) → 系统分享面板
跟 RecipeDetailOverlay.saveImage 每一步都一样。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -342,7 +342,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { ref, computed, watch, nextTick } from 'vue'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { useOilsStore, VOLUME_DROPS, DROPS_PER_ML } from '../stores/oils'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { useUiStore } from '../stores/ui'
|
||||
@@ -727,45 +728,63 @@ function exportPDF() {
|
||||
setTimeout(() => w.print(), 500)
|
||||
}
|
||||
|
||||
// Save element as image — identical to recipe card flow
|
||||
async function saveElementAsImage(el, name) {
|
||||
if (!el) { ui.showToast('找不到卡片'); return }
|
||||
const html2canvas = (await import('html2canvas')).default
|
||||
const { saveImageFromUrl } = await import('../composables/useSaveImage')
|
||||
// ──── Save image logic (identical to RecipeDetailOverlay) ────
|
||||
|
||||
// Pre-generated image URLs (same pattern as cardImageUrl in recipe card)
|
||||
const dilutionImageUrl = ref(null)
|
||||
const contraImageUrl = ref(null)
|
||||
const oilCardImageUrl = ref(null)
|
||||
|
||||
async function generateImageFromRef(elRef, imageUrlRef) {
|
||||
const el = elRef.value || elRef
|
||||
if (!el) return
|
||||
// Hide buttons during capture
|
||||
const btns = el.querySelectorAll('button')
|
||||
btns.forEach(b => { b._d = b.style.display; b.style.display = 'none' })
|
||||
|
||||
await nextTick()
|
||||
await new Promise(r => setTimeout(r, 100))
|
||||
try {
|
||||
// Same params as recipe card's generateCardImage
|
||||
const canvas = await html2canvas(el, {
|
||||
backgroundColor: null,
|
||||
scale: 3,
|
||||
useCORS: true,
|
||||
allowTaint: false,
|
||||
})
|
||||
btns.forEach(b => b.style.display = b._d || '')
|
||||
|
||||
const dataUrl = canvas.toDataURL('image/png')
|
||||
await saveImageFromUrl(dataUrl, name)
|
||||
ui.showToast('图片已保存')
|
||||
imageUrlRef.value = canvas.toDataURL('image/png')
|
||||
} catch (e) {
|
||||
console.error('generateImage failed:', e)
|
||||
} finally {
|
||||
btns.forEach(b => b.style.display = b._d || '')
|
||||
console.error('saveElementAsImage failed:', e)
|
||||
ui.showToast('截图失败: ' + (e.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
|
||||
async function saveGeneratedImage(imageUrlRef, elRef, name) {
|
||||
// Generate if not already done
|
||||
if (!imageUrlRef.value) {
|
||||
await generateImageFromRef(elRef, imageUrlRef)
|
||||
}
|
||||
if (!imageUrlRef.value) {
|
||||
ui.showToast('图片生成失败')
|
||||
return
|
||||
}
|
||||
// Same as RecipeDetailOverlay.saveImage
|
||||
const { saveImageFromUrl } = await import('../composables/useSaveImage')
|
||||
await saveImageFromUrl(imageUrlRef.value, name)
|
||||
ui.showToast('已保存图片')
|
||||
}
|
||||
|
||||
function saveDilutionImage() {
|
||||
saveElementAsImage(dilutionCardRef.value, '精油稀释比例指南')
|
||||
saveGeneratedImage(dilutionImageUrl, dilutionCardRef, '精油稀释比例指南')
|
||||
}
|
||||
function saveContraImage() {
|
||||
saveElementAsImage(contraCardRef.value, '精油使用禁忌')
|
||||
saveGeneratedImage(contraImageUrl, contraCardRef, '精油使用禁忌')
|
||||
}
|
||||
function saveCardImage(name) {
|
||||
const el = document.querySelector('.oil-card-modal')
|
||||
saveElementAsImage(el, name + '_精油知识卡')
|
||||
if (!el) { ui.showToast('找不到卡片'); return }
|
||||
// Use a temporary ref-like object
|
||||
const tmpRef = { value: el }
|
||||
saveGeneratedImage(oilCardImageUrl, tmpRef, name + '_精油知识卡')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user