feat: add download route and view, implement image download functionality, and enhance QR code sharing in PickupView
This commit is contained in:
@@ -39,6 +39,11 @@ const router = createRouter({
|
|||||||
name: 'pickup',
|
name: 'pickup',
|
||||||
component: () => import('../views/PickupView.vue'),
|
component: () => import('../views/PickupView.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/download',
|
||||||
|
name: 'download',
|
||||||
|
component: () => import('../views/DownloadView.vue'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
262
src/views/DownloadView.vue
Normal file
262
src/views/DownloadView.vue
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const imageParam = ref('')
|
||||||
|
const hasError = ref(false)
|
||||||
|
const isDownloading = ref(false)
|
||||||
|
const downloadSuccess = ref(false)
|
||||||
|
|
||||||
|
const imageUrl = computed(() => {
|
||||||
|
if (imageParam.value) {
|
||||||
|
return `https://assets.dekthai-online.com/static/photobooth/${imageParam.value}`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const downloadImage = async () => {
|
||||||
|
if (!imageUrl.value || isDownloading.value) return
|
||||||
|
|
||||||
|
isDownloading.value = true
|
||||||
|
downloadSuccess.value = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create a temporary link element for download
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = imageUrl.value
|
||||||
|
link.download = imageParam.value || 'photobooth-image.jpg'
|
||||||
|
link.style.display = 'none'
|
||||||
|
|
||||||
|
// Add to DOM, click, and remove
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
downloadSuccess.value = true
|
||||||
|
|
||||||
|
// Hide success message after 3 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
downloadSuccess.value = false
|
||||||
|
}, 3000)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Download failed:', error)
|
||||||
|
hasError.value = true
|
||||||
|
} finally {
|
||||||
|
isDownloading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Get image parameter from URL query
|
||||||
|
const image = route.query.image as string
|
||||||
|
if (image) {
|
||||||
|
imageParam.value = image
|
||||||
|
} else {
|
||||||
|
hasError.value = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="download-container">
|
||||||
|
<header class="header">
|
||||||
|
<h1>ดาวน์โหลดรูปภาพ</h1>
|
||||||
|
<p>รูปภาพของคุณพร้อมให้ดาวน์โหลด</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section v-if="!hasError && imageUrl" class="download-section">
|
||||||
|
<div class="download-actions">
|
||||||
|
<button @click="downloadImage" :disabled="isDownloading" class="download-button">
|
||||||
|
<span v-if="isDownloading" class="button-icon">⏳</span>
|
||||||
|
<span v-else class="button-icon">📥</span>
|
||||||
|
{{ isDownloading ? 'กำลังดาวน์โหลด...' : 'ดาวน์โหลดรูปภาพ' }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div v-if="downloadSuccess" class="success-message">
|
||||||
|
✅ ดาวน์โหลดสำเร็จ! ไฟล์ได้บันทึกในเครื่องของคุณแล้ว
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="image-display">
|
||||||
|
<img :src="imageUrl" alt="Photo for download" class="download-image" @error="hasError = true" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section v-else class="error-section">
|
||||||
|
<div class="error-message">
|
||||||
|
<h2>ไม่พบรูปภาพ</h2>
|
||||||
|
<p>ไม่สามารถโหลดรูปภาพได้ กรุณาตรวจสอบลิงก์อีกครั้ง</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Crete+Round&family=Old+Standard+TT&display=swap');
|
||||||
|
|
||||||
|
.download-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: #fdfaf6;
|
||||||
|
color: #3e2723;
|
||||||
|
font-family: 'Old Standard TT', serif;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: #5d4037;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-family: 'Crete Round', serif;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header p {
|
||||||
|
color: #6d4c41;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-display {
|
||||||
|
background: #e0d8cf;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 5px 20px rgba(0,0,0,0.15);
|
||||||
|
border: 4px solid #a1887f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-image {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: block;
|
||||||
|
filter: sepia(0.1) brightness(0.95);
|
||||||
|
max-height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-actions {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button {
|
||||||
|
background: #8d6e63;
|
||||||
|
color: #fdfaf6;
|
||||||
|
border: 2px solid #795548;
|
||||||
|
padding: 1rem 2.5rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
|
||||||
|
font-family: 'Crete Round', serif;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button:hover {
|
||||||
|
background: #795548;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 15px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-section {
|
||||||
|
text-align: center;
|
||||||
|
background: #e0d8cf;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 5px 20px rgba(0,0,0,0.15);
|
||||||
|
border: 2px solid #bcaaa4;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message h2 {
|
||||||
|
color: #d32f2f;
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-family: 'Crete Round', serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message p {
|
||||||
|
color: #6d4c41;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button:disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
cursor: not-allowed;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button:disabled:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-message {
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
animation: fadeIn 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.download-image {
|
||||||
|
max-height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-button {
|
||||||
|
width: 280px;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding: 0.8rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -33,7 +33,7 @@ const examplePhotos = ref([
|
|||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="examples-section" style="margin-top: 1rem;">
|
<section class="examples-section" style="margin-top: 1rem; display: none;">
|
||||||
<!-- <h2>ตัวอย่างผลงาน</h2> -->
|
<!-- <h2>ตัวอย่างผลงาน</h2> -->
|
||||||
<div class="photo-examples">
|
<div class="photo-examples">
|
||||||
<div class="example-strip">
|
<div class="example-strip">
|
||||||
|
|||||||
@@ -10,6 +10,20 @@ const cachedImageUrl = ref('')
|
|||||||
const isGeneratingImage = ref(false)
|
const isGeneratingImage = ref(false)
|
||||||
const hasError = ref(false)
|
const hasError = ref(false)
|
||||||
|
|
||||||
|
const qrCodeUrl = computed(() => {
|
||||||
|
const filename = localStorage.getItem('photobooth-uploaded-filename')
|
||||||
|
if (filename) {
|
||||||
|
return `https://api.dekthai-online.com/apu-school/qrcode/photobooth.php?key=${filename}`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
const downloadPageUrl = computed(() => {
|
||||||
|
const filename = localStorage.getItem('photobooth-uploaded-filename')
|
||||||
|
if (filename) {
|
||||||
|
return `${window.location.origin}/download?image=${filename}`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// โหลดข้อมูลจาก localStorage
|
// โหลดข้อมูลจาก localStorage
|
||||||
const savedPhotos = localStorage.getItem('photobooth-photos')
|
const savedPhotos = localStorage.getItem('photobooth-photos')
|
||||||
@@ -281,7 +295,22 @@ const startOver = () => {
|
|||||||
<span class="button-icon">📥</span>
|
<span class="button-icon">📥</span>
|
||||||
ดาวน์โหลด
|
ดาวน์โหลด
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button @click="startOver" class="start-over-button">
|
||||||
|
เริ่มใหม่
|
||||||
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- QR Code สำหรับ download รูปถ่าย -->
|
||||||
|
<div v-if="qrCodeUrl" class="qr-code-section">
|
||||||
|
<h3>สแกน QR Code เพื่อดาวน์โหลด</h3>
|
||||||
|
<a :href="downloadPageUrl" target="_blank" class="qr-code-link">
|
||||||
|
<img :src="qrCodeUrl" alt="QR Code for downloading photo" class="qr-code-image" />
|
||||||
|
</a>
|
||||||
|
<p class="qr-hint">หรือ <a :href="downloadPageUrl" target="_blank" class="download-link">คลิกที่นี่</a> เพื่อเปิดในแท็บใหม่</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="result-section">
|
<section class="result-section">
|
||||||
@@ -293,6 +322,7 @@ const startOver = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img v-else-if="cachedImageUrl" :src="cachedImageUrl" alt="Combined Photo" class="combined-image" />
|
<img v-else-if="cachedImageUrl" :src="cachedImageUrl" alt="Combined Photo" class="combined-image" />
|
||||||
|
|
||||||
<div v-else-if="hasError" class="error-message">
|
<div v-else-if="hasError" class="error-message">
|
||||||
<p>ไม่สามารถสร้างภาพได้</p>
|
<p>ไม่สามารถสร้างภาพได้</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -302,11 +332,9 @@ const startOver = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section class="footer-section">
|
<!-- <section class="footer-section">
|
||||||
<button @click="startOver" class="start-over-button">
|
|
||||||
เริ่มใหม่
|
</section> -->
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -408,6 +436,47 @@ const startOver = () => {
|
|||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-code-section {
|
||||||
|
margin-top: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-code-section h3 {
|
||||||
|
color: #5d4037;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-family: 'Crete Round', serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-code-image {
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
border: 2px solid #a1887f;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-code-link:hover .qr-code-image {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-hint {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #6d4c41;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-link {
|
||||||
|
color: #8d6e63;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-link:hover {
|
||||||
|
color: #795548;
|
||||||
|
}
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1.5rem; /* Increased gap */
|
gap: 1.5rem; /* Increased gap */
|
||||||
@@ -421,7 +490,7 @@ const startOver = () => {
|
|||||||
padding: 1rem 2.5rem; /* Larger padding */
|
padding: 1rem 2.5rem; /* Larger padding */
|
||||||
font-size: 1.2rem; /* Slightly larger font */
|
font-size: 1.2rem; /* Slightly larger font */
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-radius: 8px; /* Softer border-radius */
|
border-radius: 20px; /* Softer border-radius */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -454,7 +523,7 @@ const startOver = () => {
|
|||||||
padding: 0.8rem 1.8rem; /* Adjusted padding */
|
padding: 0.8rem 1.8rem; /* Adjusted padding */
|
||||||
font-size: 1rem; /* Slightly smaller font */
|
font-size: 1rem; /* Slightly smaller font */
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-radius: 5px; /* Softer border-radius */
|
border-radius: 20px; /* Softer border-radius */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||||
|
|||||||
@@ -31,10 +31,56 @@ onMounted(() => {
|
|||||||
// เริ่มนับถอยหลัง
|
// เริ่มนับถอยหลัง
|
||||||
startCountdown()
|
startCountdown()
|
||||||
|
|
||||||
// Load the final image from localStorage
|
// // Load the final image from localStorage
|
||||||
finalImage.value = localStorage.getItem('photobooth-final-image');
|
// finalImage.value = localStorage.getItem('photobooth-final-image');
|
||||||
|
|
||||||
|
// // Upload the final image to the server
|
||||||
|
// if (finalImage.value) {
|
||||||
|
// uploadFinalImage(finalImage.value);
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const uploadFinalImage = async (imageDataUrl: string) => {
|
||||||
|
try {
|
||||||
|
// Compress the image first to reduce size
|
||||||
|
console.log('Original image size:', imageDataUrl.length);
|
||||||
|
const compressedImage = await compressImage(imageDataUrl, 0.8); // 80% quality
|
||||||
|
console.log('Compressed image size:', compressedImage.length);
|
||||||
|
|
||||||
|
// Convert compressed base64 data URL to Blob
|
||||||
|
const response = await fetch(compressedImage);
|
||||||
|
const blob = await response.blob();
|
||||||
|
|
||||||
|
// Create FormData
|
||||||
|
const formData = new FormData();
|
||||||
|
const file = new File([blob], 'photobooth-final.jpg', { type: 'image/jpeg' });
|
||||||
|
formData.append('profile_image', file, file.name);
|
||||||
|
|
||||||
|
// Upload to API
|
||||||
|
const uploadResponse = await fetch('https://api2.dekthai-online.com/g/upload/photobooth', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
if (uploadResponse.ok) {
|
||||||
|
const result = await uploadResponse.json();
|
||||||
|
console.log('Upload successful:', result);
|
||||||
|
|
||||||
|
// Save the filename to localStorage
|
||||||
|
if (result.filename) {
|
||||||
|
localStorage.setItem('photobooth-uploaded-filename', result.filename);
|
||||||
|
console.log('Filename saved to localStorage:', result.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.error('Upload failed:', uploadResponse.status, uploadResponse.statusText);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error uploading image:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const startCountdown = () => {
|
const startCountdown = () => {
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
countdown.value--
|
countdown.value--
|
||||||
@@ -232,12 +278,24 @@ const generateAndCacheImage = async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// สร้าง PNG data URL และบันทึกใน localStorage
|
// สร้าง compressed JPEG data URL และบันทึกใน localStorage
|
||||||
const dataUrl = canvas.toDataURL('image/png')
|
const dataUrl = canvas.toDataURL('image/jpeg', 0.8) // 80% quality JPEG
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saveToLocalStorage('photobooth-final-image', dataUrl);
|
saveToLocalStorage('photobooth-final-image', dataUrl);
|
||||||
finalImage.value = dataUrl;
|
finalImage.value = dataUrl;
|
||||||
|
|
||||||
|
|
||||||
|
// Load the final image from localStorage
|
||||||
|
finalImage.value = localStorage.getItem('photobooth-final-image');
|
||||||
|
|
||||||
|
// Upload the final image to the server
|
||||||
|
if (finalImage.value) {
|
||||||
|
uploadFinalImage(dataUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof DOMException && error.name === 'QuotaExceededError') {
|
if (error instanceof DOMException && error.name === 'QuotaExceededError') {
|
||||||
console.error('localStorage quota exceeded for cached image')
|
console.error('localStorage quota exceeded for cached image')
|
||||||
@@ -311,9 +369,9 @@ onMounted(() => {
|
|||||||
<p>กำลังเตรียมไฟล์สำหรับดาวน์โหลด...</p>
|
<p>กำลังเตรียมไฟล์สำหรับดาวน์โหลด...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="final-image-display">
|
<!-- <div class="final-image-display">
|
||||||
<img v-if="finalImage" :src="finalImage" alt="Final Combined Image" />
|
<img v-if="finalImage" :src="finalImage" alt="Final Combined Image" />
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
<div class="loading-indicator">
|
<div class="loading-indicator">
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default defineConfig({
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
allowedHosts: ['photobooth.lookmeblog.com']
|
allowedHosts: ['photobooth.lookmeblog.com', 'photobooth.dekthai-online.com']
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
Reference in New Issue
Block a user