import { ref, nextTick } from 'vue' import QRCode from 'qrcode' const BASE_QR_SIZE = 256 const MAX_WIDTH_RATIO = 0.8 const MIN_SCALE = 0.5 const SCALE_STEP = 0.1 export function useQrCode() { const textInput = ref('') const error = ref('') const errorColor = ref('red') const scale = ref(1) const hasQr = ref(false) const qrCanvasRef = ref(null) const qrFrameRef = ref(null) function logMessage(message, color = 'red') { error.value = message errorColor.value = color } function getFrameWidth() { return qrFrameRef.value?.getBoundingClientRect().width ?? 0 } function getMaxWidth() { return window.innerWidth * MAX_WIDTH_RATIO } function persistScale() { localStorage.setItem('scale', String(scale.value)) } async function renderQrCanvas() { const canvas = qrCanvasRef.value const userText = textInput.value.trim() if (!canvas || !userText) return const width = Math.round(BASE_QR_SIZE * scale.value) await QRCode.toCanvas(canvas, userText, { width }) } async function clampScaleIfNeeded() { await nextTick() if (getFrameWidth() > getMaxWidth()) { scale.value = 1 persistScale() await renderQrCanvas() } } async function generateQR() { const userText = textInput.value.trim() if (!userText) { logMessage('Введите текст для генерации QR-кода!') return } localStorage.setItem('userText', userText) hasQr.value = true await nextTick() try { await renderQrCanvas() logMessage('') await clampScaleIfNeeded() } catch (err) { console.error(err) logMessage('Ошибка при генерации QR-кода.') hasQr.value = false } } function downloadQR() { const userText = textInput.value.slice(0, 20) const canvas = qrCanvasRef.value if (!canvas) { logMessage('QR-код не сгенерирован!') return } if (!userText) { logMessage('Отсутствует текст в поле для ввода') return } const link = document.createElement('a') link.href = canvas.toDataURL('image/png') link.download = `qr-code-${userText}.png` link.click() logMessage('QR-код скачан!', 'green') } function clearQR() { textInput.value = '' hasQr.value = false error.value = '' scale.value = 1 localStorage.removeItem('userText') localStorage.removeItem('scale') } function closeQrModal() { hasQr.value = false } async function zoomIn() { if (!qrFrameRef.value || !textInput.value.trim()) { logMessage('До генерации QR кода маштаб менять нельзя') return } const previousScale = scale.value scale.value += SCALE_STEP await renderQrCanvas() await nextTick() if (getFrameWidth() > getMaxWidth()) { scale.value = previousScale await renderQrCanvas() logMessage('Достигнут максимальный размер QR кода') return } persistScale() logMessage('') } async function zoomOut() { if (!qrFrameRef.value || !textInput.value.trim()) { logMessage('До генерации QR кода маштаб менять нельзя') return } if (scale.value <= MIN_SCALE) { logMessage('Достигнут минимальный размер QR кода') return } scale.value -= SCALE_STEP await renderQrCanvas() persistScale() logMessage('') } async function restoreFromStorage() { const savedScale = localStorage.getItem('scale') if (savedScale) { scale.value = Number(savedScale) } const savedText = localStorage.getItem('userText') if (savedText) { textInput.value = savedText await generateQR() } } return { textInput, error, errorColor, hasQr, qrCanvasRef, qrFrameRef, generateQR, downloadQR, clearQR, closeQrModal, zoomIn, zoomOut, restoreFromStorage, } }