156 lines
4.9 KiB
Vue
156 lines
4.9 KiB
Vue
<template>
|
|
<div class="flex flex-col min-h-screen">
|
|
<main class="flex-grow flex items-center justify-center py-6 px-4 md:px-6">
|
|
<section class="max-w-prose w-full flex flex-col gap-1">
|
|
<h2 class="text-xl font-semibold mb-4">Ваш QR‑код готов</h2>
|
|
<p class="text-gray-600 mb-4">Сохраните его и ознакомьтесь с инструкциями по размещению.</p>
|
|
|
|
<!-- Рендер QR‑кода -->
|
|
<div v-if="!svgQueryIsLoading && svgQueryData" class="border p-4 bg-white rounded-lg mb-6">
|
|
<img :src="svgQueryData" alt="QR‑код" />
|
|
</div>
|
|
|
|
<!-- Сообщение об ошибке -->
|
|
<p v-if="qrCodeQueryIsError" class="text-red-500 mt-4">
|
|
Ошибка загрузки данных QR‑кода: {{ qrCodeQueryError!.message }}
|
|
</p>
|
|
<p v-if="svgQueryIsLoading" class="text-gray-500 mt-4">Загрузка...</p>
|
|
|
|
<!-- Кнопки для скачивания -->
|
|
<div
|
|
v-if="!svgQueryIsLoading && !qrCodeQueryIsError && svgQueryData"
|
|
class="flex flex-row gap-4 justify-center"
|
|
>
|
|
<Button
|
|
label="Скачать SVG"
|
|
icon="pi pi-download"
|
|
class="p-button-sm"
|
|
:href="svgQueryData"
|
|
:download="`${sanitizedFileName}.svg`"
|
|
as="a"
|
|
/>
|
|
<Button
|
|
label="Скачать PNG"
|
|
icon="pi pi-download"
|
|
class="p-button-sm p-button-outlined"
|
|
@click="downloadPng"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Инструкции по размещению -->
|
|
<ManagePlacementInstructions
|
|
:placement="qrCodeDoc?.placement"
|
|
v-if="qrCodeDoc?.placement"
|
|
/>
|
|
</section>
|
|
</main>
|
|
|
|
<footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700">
|
|
<p>
|
|
Нужен еще один?
|
|
<a href="/create" class="underline">Создайте QR‑код</a>.
|
|
</p>
|
|
<p class="mt-1">
|
|
Сделайте НаСвязи удобнее. Будем рады вашей <a href="/donate" class="underline"
|
|
>поддержке</a
|
|
>.
|
|
</p>
|
|
</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useQuery } from '@tanstack/vue-query'
|
|
import QRCodeStyling from 'qr-code-styling'
|
|
import { optimize } from 'svgo'
|
|
import { getQrCodeDocument } from '@/api/qrCode'
|
|
import { type QRCodeDocument } from '@/types/DBDocumentTypes'
|
|
|
|
const { qr_code_uri } = defineProps<{ qr_code_uri: QRCodeDocument['uri'] }>()
|
|
|
|
// Хук для загрузки данных QR‑кода
|
|
const {
|
|
data: qrCodeDoc,
|
|
isError: qrCodeQueryIsError,
|
|
error: qrCodeQueryError,
|
|
} = useQuery({
|
|
queryKey: ['qrCode', computed(() => qr_code_uri)],
|
|
queryFn: () => getQrCodeDocument(qr_code_uri),
|
|
})
|
|
|
|
// Инициализация QRCodeStyling
|
|
const qrCode = new QRCodeStyling({
|
|
width: 256 * 4,
|
|
height: 256 * 4,
|
|
data: '',
|
|
type: 'svg',
|
|
backgroundOptions: {
|
|
color: '#ffffff',
|
|
},
|
|
})
|
|
|
|
// Получение имени файла
|
|
const sanitizedFileName = computed(() => {
|
|
const sanitized = qrCodeDoc.value?.name
|
|
?.replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // Убираем запрещённые символы
|
|
.replace(/\s+/g, '_') // Заменяем пробелы на подчёркивания
|
|
.trim()
|
|
return sanitized ? `${sanitized}_QR-Code_HereConnect` : 'QR-Code_HereConnect'
|
|
})
|
|
|
|
// Хук для генерации и оптимизации SVG
|
|
const {
|
|
isLoading: svgQueryIsLoading,
|
|
data: svgQueryData,
|
|
error: svgQueryError,
|
|
} = useQuery({
|
|
queryKey: ['svg', computed(() => qr_code_uri)],
|
|
enabled: computed(() => !!qrCodeDoc.value?.url),
|
|
queryFn: async () => {
|
|
qrCode.update({ data: qrCodeDoc.value!.url })
|
|
|
|
const blob = await qrCode.getRawData('svg')
|
|
if (blob && blob instanceof Blob) {
|
|
const text = await blob.text()
|
|
|
|
const optimizedSvg = optimize(text, {
|
|
plugins: [
|
|
{ name: 'removeDoctype' },
|
|
{ name: 'removeComments' },
|
|
{ name: 'removeDimensions' },
|
|
{ name: 'convertShapeToPath' },
|
|
{ name: 'convertPathData' },
|
|
{ name: 'mergePaths' },
|
|
],
|
|
})
|
|
|
|
if (optimizedSvg.data) {
|
|
return URL.createObjectURL(new Blob([optimizedSvg.data], { type: 'image/svg+xml' }))
|
|
} else {
|
|
throw new Error('Ошибка оптимизации SVG')
|
|
}
|
|
} else {
|
|
throw new Error('Ошибка генерации QR‑кода')
|
|
}
|
|
},
|
|
onSettled(data) {
|
|
if (!data && svgQueryError) {
|
|
console.error('Ошибка загрузки SVG:', svgQueryError.message)
|
|
}
|
|
},
|
|
})
|
|
|
|
// Скачивание PNG
|
|
async function downloadPng() {
|
|
try {
|
|
await qrCode.download({
|
|
name: sanitizedFileName.value,
|
|
extension: 'png',
|
|
})
|
|
} catch (err) {
|
|
console.error('Ошибка скачивания PNG:', err)
|
|
}
|
|
}
|
|
</script>
|