Spaces:
Running
Running
| <html lang="vi"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Office File Converter - Công cụ chuyển đổi file văn phòng</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .file-drop-area { | |
| border: 2px dashed #3b82f6; | |
| transition: all 0.3s ease; | |
| } | |
| .file-drop-area.active { | |
| border-color: #10b981; | |
| background-color: #f0fdf4; | |
| } | |
| .progress-bar { | |
| transition: width 0.3s ease; | |
| } | |
| .convert-btn:disabled { | |
| opacity: 0.7; | |
| cursor: not-allowed; | |
| } | |
| .file-icon { | |
| font-size: 2.5rem; | |
| } | |
| .toast { | |
| animation: slideIn 0.3s, fadeOut 0.5s 2.5s forwards; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateY(20px); opacity: 0; } | |
| to { transform: translateY(0); opacity: 1; } | |
| } | |
| @keyframes fadeOut { | |
| to { opacity: 0; } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="text-center mb-10"> | |
| <h1 class="text-3xl md:text-4xl font-bold text-blue-600 mb-2"> | |
| <i class="fas fa-file-export mr-2"></i>Office File Converter | |
| </h1> | |
| <p class="text-gray-600 max-w-2xl mx-auto"> | |
| Công cụ chuyển đổi file văn phòng trực tuyến miễn phí. Hỗ trợ DOCX, PDF, XLSX, PPTX và nhiều định dạng khác. | |
| </p> | |
| </header> | |
| <!-- Main Converter --> | |
| <div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8"> | |
| <div class="flex flex-col md:flex-row gap-6"> | |
| <!-- File Input Section --> | |
| <div class="w-full md:w-1/2"> | |
| <div id="fileDropArea" class="file-drop-area rounded-lg p-8 text-center cursor-pointer h-full flex flex-col items-center justify-center"> | |
| <i class="fas fa-cloud-upload-alt file-icon text-blue-400 mb-4"></i> | |
| <h3 class="text-lg font-semibold mb-2">Kéo & thả file vào đây</h3> | |
| <p class="text-gray-500 mb-4">hoặc</p> | |
| <label for="fileInput" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-2 rounded-md cursor-pointer transition"> | |
| <i class="fas fa-folder-open mr-2"></i>Chọn file | |
| </label> | |
| <input type="file" id="fileInput" class="hidden"> | |
| <p class="text-xs text-gray-400 mt-4">Hỗ trợ: DOCX, PDF, XLSX, PPTX, TXT, RTF, ODT</p> | |
| </div> | |
| </div> | |
| <!-- Conversion Options --> | |
| <div class="w-full md:w-1/2"> | |
| <div class="bg-gray-50 rounded-lg p-6 h-full"> | |
| <h3 class="text-lg font-semibold mb-4 flex items-center"> | |
| <i class="fas fa-cog text-blue-500 mr-2"></i> Tùy chọn chuyển đổi | |
| </h3> | |
| <!-- Selected File Info --> | |
| <div id="fileInfo" class="hidden mb-4 p-3 bg-blue-50 rounded-md"> | |
| <div class="flex items-center justify-between"> | |
| <div class="flex items-center truncate"> | |
| <i id="fileTypeIcon" class="fas fa-file mr-2 text-blue-500"></i> | |
| <span id="fileName" class="font-medium truncate"></span> | |
| </div> | |
| <button id="removeFile" class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div id="fileSize" class="text-xs text-gray-500 mt-1"></div> | |
| </div> | |
| <!-- Format Selection --> | |
| <div class="mb-4"> | |
| <label class="block text-sm font-medium text-gray-700 mb-2">Chuyển đổi sang:</label> | |
| <div class="grid grid-cols-3 gap-2"> | |
| <button data-format="pdf" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-pdf text-red-500 mb-1"></i> | |
| <span>PDF</span> | |
| </button> | |
| <button data-format="docx" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-word text-blue-500 mb-1"></i> | |
| <span>DOCX</span> | |
| </button> | |
| <button data-format="xlsx" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-excel text-green-500 mb-1"></i> | |
| <span>XLSX</span> | |
| </button> | |
| <button data-format="pptx" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-powerpoint text-orange-500 mb-1"></i> | |
| <span>PPTX</span> | |
| </button> | |
| <button data-format="txt" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-alt text-gray-500 mb-1"></i> | |
| <span>TXT</span> | |
| </button> | |
| <button data-format="odt" class="format-btn py-2 px-3 rounded-md border hover:bg-blue-50 hover:border-blue-300 flex flex-col items-center"> | |
| <i class="fas fa-file-alt text-purple-500 mb-1"></i> | |
| <span>ODT</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Advanced Options --> | |
| <div class="mb-4"> | |
| <div class="flex items-center justify-between cursor-pointer" id="advancedToggle"> | |
| <span class="text-sm font-medium text-gray-700">Tùy chọn nâng cao</span> | |
| <i class="fas fa-chevron-down text-gray-500 transition-transform"></i> | |
| </div> | |
| <div id="advancedOptions" class="hidden mt-2 space-y-2"> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="preserveFormatting" class="mr-2"> | |
| <label for="preserveFormatting" class="text-sm">Giữ nguyên định dạng</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="optimizeForWeb" class="mr-2"> | |
| <label for="optimizeForWeb" class="text-sm">Tối ưu cho web</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="passwordProtect" class="mr-2"> | |
| <label for="passwordProtect" class="text-sm">Bảo vệ bằng mật khẩu</label> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Convert Button --> | |
| <button id="convertBtn" class="convert-btn w-full bg-blue-600 hover:bg-blue-700 text-white py-3 px-4 rounded-md font-medium transition disabled:opacity-70 disabled:cursor-not-allowed" disabled> | |
| <i class="fas fa-exchange-alt mr-2"></i> Chuyển đổi | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Progress Bar (Hidden by default) --> | |
| <div id="progressContainer" class="max-w-4xl mx-auto hidden mb-8"> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden p-6"> | |
| <h3 class="text-lg font-semibold mb-4 flex items-center"> | |
| <i class="fas fa-spinner fa-spin text-blue-500 mr-2"></i> Đang xử lý... | |
| </h3> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="progressBar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div> | |
| </div> | |
| <div class="flex justify-between text-sm text-gray-500 mt-2"> | |
| <span id="progressText">0%</span> | |
| <span id="timeRemaining">Ước tính: vài giây</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Result Section (Hidden by default) --> | |
| <div id="resultContainer" class="max-w-4xl mx-auto hidden"> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden"> | |
| <div class="p-6"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h3 class="text-lg font-semibold flex items-center"> | |
| <i class="fas fa-check-circle text-green-500 mr-2"></i> Chuyển đổi thành công! | |
| </h3> | |
| <button id="newConversion" class="text-blue-500 hover:text-blue-700 text-sm font-medium"> | |
| <i class="fas fa-redo mr-1"></i> Chuyển đổi mới | |
| </button> | |
| </div> | |
| <div class="flex flex-col md:flex-row gap-6"> | |
| <div class="flex-1 bg-gray-50 rounded-lg p-4"> | |
| <div class="flex items-center mb-3"> | |
| <i id="originalFileIcon" class="fas fa-file text-blue-500 mr-2"></i> | |
| <div> | |
| <div id="originalFileName" class="font-medium"></div> | |
| <div id="originalFileSize" class="text-xs text-gray-500"></div> | |
| </div> | |
| </div> | |
| <div class="text-sm text-gray-600 mb-2"> | |
| <span class="font-medium">Loại file:</span> | |
| <span id="originalFileType"></span> | |
| </div> | |
| </div> | |
| <div class="flex items-center justify-center text-gray-400"> | |
| <i class="fas fa-arrow-right text-2xl"></i> | |
| </div> | |
| <div class="flex-1 bg-green-50 rounded-lg p-4"> | |
| <div class="flex items-center mb-3"> | |
| <i id="convertedFileIcon" class="fas fa-file text-green-500 mr-2"></i> | |
| <div> | |
| <div id="convertedFileName" class="font-medium"></div> | |
| <div id="convertedFileSize" class="text-xs text-gray-500"></div> | |
| </div> | |
| </div> | |
| <div class="text-sm text-gray-600 mb-2"> | |
| <span class="font-medium">Loại file:</span> | |
| <span id="convertedFileType"></span> | |
| </div> | |
| <div class="flex gap-2 mt-4"> | |
| <button id="downloadBtn" class="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-md text-sm font-medium flex items-center"> | |
| <i class="fas fa-download mr-2"></i> Tải xuống | |
| </button> | |
| <button id="shareBtn" class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-md text-sm font-medium flex items-center"> | |
| <i class="fas fa-share-alt mr-2"></i> Chia sẻ | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Features Section --> | |
| <div class="max-w-4xl mx-auto mt-12 mb-8"> | |
| <h2 class="text-2xl font-bold text-center mb-8">Tính năng nổi bật</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="text-blue-500 mb-3"> | |
| <i class="fas fa-bolt text-2xl"></i> | |
| </div> | |
| <h3 class="font-semibold mb-2">Tốc độ nhanh</h3> | |
| <p class="text-gray-600 text-sm">Xử lý file chỉ trong vài giây với công nghệ đám mây hiện đại.</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="text-green-500 mb-3"> | |
| <i class="fas fa-lock text-2xl"></i> | |
| </div> | |
| <h3 class="font-semibold mb-2">Bảo mật tuyệt đối</h3> | |
| <p class="text-gray-600 text-sm">File của bạn sẽ tự động xóa sau 1 giờ, không lưu trữ dữ liệu.</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="text-purple-500 mb-3"> | |
| <i class="fas fa-mobile-alt text-2xl"></i> | |
| </div> | |
| <h3 class="font-semibold mb-2">Mọi thiết bị</h3> | |
| <p class="text-gray-600 text-sm">Tương thích với mọi trình duyệt và thiết bị di động.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Toast Notification --> | |
| <div id="toast" class="toast fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-md shadow-lg hidden"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-check-circle mr-2"></i> | |
| <span id="toastMessage"></span> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const fileDropArea = document.getElementById('fileDropArea'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const fileInfo = document.getElementById('fileInfo'); | |
| const fileName = document.getElementById('fileName'); | |
| const fileSize = document.getElementById('fileSize'); | |
| const fileTypeIcon = document.getElementById('fileTypeIcon'); | |
| const removeFile = document.getElementById('removeFile'); | |
| const formatBtns = document.querySelectorAll('.format-btn'); | |
| const convertBtn = document.getElementById('convertBtn'); | |
| const progressContainer = document.getElementById('progressContainer'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const progressText = document.getElementById('progressText'); | |
| const timeRemaining = document.getElementById('timeRemaining'); | |
| const resultContainer = document.getElementById('resultContainer'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const shareBtn = document.getElementById('shareBtn'); | |
| const newConversion = document.getElementById('newConversion'); | |
| const advancedToggle = document.getElementById('advancedToggle'); | |
| const advancedOptions = document.getElementById('advancedOptions'); | |
| const toast = document.getElementById('toast'); | |
| const toastMessage = document.getElementById('toastMessage'); | |
| // Variables | |
| let selectedFile = null; | |
| let selectedFormat = null; | |
| const fileIcons = { | |
| 'pdf': 'file-pdf', | |
| 'docx': 'file-word', | |
| 'xlsx': 'file-excel', | |
| 'pptx': 'file-powerpoint', | |
| 'txt': 'file-alt', | |
| 'rtf': 'file-alt', | |
| 'odt': 'file-alt', | |
| 'default': 'file' | |
| }; | |
| const fileColors = { | |
| 'pdf': 'text-red-500', | |
| 'docx': 'text-blue-500', | |
| 'xlsx': 'text-green-500', | |
| 'pptx': 'text-orange-500', | |
| 'txt': 'text-gray-500', | |
| 'rtf': 'text-gray-500', | |
| 'odt': 'text-purple-500', | |
| 'default': 'text-blue-500' | |
| }; | |
| // Event Listeners | |
| fileDropArea.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| fileDropArea.classList.add('active'); | |
| }); | |
| fileDropArea.addEventListener('dragleave', () => { | |
| fileDropArea.classList.remove('active'); | |
| }); | |
| fileDropArea.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| fileDropArea.classList.remove('active'); | |
| if (e.dataTransfer.files.length) { | |
| handleFileSelection(e.dataTransfer.files[0]); | |
| } | |
| }); | |
| fileInput.addEventListener('change', () => { | |
| if (fileInput.files.length) { | |
| handleFileSelection(fileInput.files[0]); | |
| } | |
| }); | |
| removeFile.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| resetFileSelection(); | |
| }); | |
| formatBtns.forEach(btn => { | |
| btn.addEventListener('click', () => { | |
| formatBtns.forEach(b => b.classList.remove('border-blue-500', 'bg-blue-100')); | |
| btn.classList.add('border-blue-500', 'bg-blue-100'); | |
| selectedFormat = btn.getAttribute('data-format'); | |
| updateConvertButtonState(); | |
| }); | |
| }); | |
| convertBtn.addEventListener('click', startConversion); | |
| newConversion.addEventListener('click', resetConversion); | |
| advancedToggle.addEventListener('click', toggleAdvancedOptions); | |
| downloadBtn.addEventListener('click', simulateDownload); | |
| shareBtn.addEventListener('click', showShareOptions); | |
| // Functions | |
| function handleFileSelection(file) { | |
| // Check file size (max 10MB) | |
| if (file.size > 10 * 1024 * 1024) { | |
| showToast('File quá lớn. Vui lòng chọn file nhỏ hơn 10MB.'); | |
| return; | |
| } | |
| selectedFile = file; | |
| // Update UI | |
| fileName.textContent = file.name; | |
| fileSize.textContent = formatFileSize(file.size); | |
| // Set file icon based on extension | |
| const fileExt = getFileExtension(file.name); | |
| const iconClass = fileIcons[fileExt] || fileIcons['default']; | |
| const colorClass = fileColors[fileExt] || fileColors['default']; | |
| // Reset all classes and add new ones | |
| fileTypeIcon.className = 'fas mr-2'; | |
| fileTypeIcon.classList.add(`fa-${iconClass}`, colorClass); | |
| fileInfo.classList.remove('hidden'); | |
| updateConvertButtonState(); | |
| } | |
| function resetFileSelection() { | |
| selectedFile = null; | |
| fileInput.value = ''; | |
| fileInfo.classList.add('hidden'); | |
| updateConvertButtonState(); | |
| } | |
| function getFileExtension(filename) { | |
| return filename.split('.').pop().toLowerCase(); | |
| } | |
| function formatFileSize(bytes) { | |
| if (bytes === 0) return '0 Bytes'; | |
| const k = 1024; | |
| const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; | |
| } | |
| function updateConvertButtonState() { | |
| convertBtn.disabled = !(selectedFile && selectedFormat); | |
| } | |
| function startConversion() { | |
| if (!selectedFile || !selectedFormat) return; | |
| // Show progress | |
| progressContainer.classList.remove('hidden'); | |
| resultContainer.classList.add('hidden'); | |
| // Simulate conversion progress | |
| let progress = 0; | |
| const interval = setInterval(() => { | |
| progress += Math.random() * 10; | |
| if (progress > 100) progress = 100; | |
| progressBar.style.width = `${progress}%`; | |
| progressText.textContent = `${Math.round(progress)}%`; | |
| // Update time remaining | |
| const remaining = Math.max(0, Math.round((100 - progress) / 10)); | |
| timeRemaining.textContent = remaining > 0 ? | |
| `Ước tính: ${remaining} giây` : 'Đang hoàn tất...'; | |
| if (progress === 100) { | |
| clearInterval(interval); | |
| setTimeout(showResult, 500); | |
| } | |
| }, 300); | |
| } | |
| function showResult() { | |
| progressContainer.classList.add('hidden'); | |
| resultContainer.classList.remove('hidden'); | |
| // Set original file info | |
| document.getElementById('originalFileName').textContent = selectedFile.name; | |
| document.getElementById('originalFileSize').textContent = formatFileSize(selectedFile.size); | |
| const fileExt = getFileExtension(selectedFile.name); | |
| document.getElementById('originalFileType').textContent = fileExt.toUpperCase(); | |
| const originalIconClass = fileIcons[fileExt] || fileIcons['default']; | |
| const originalColorClass = fileColors[fileExt] || fileColors['default']; | |
| const originalFileIcon = document.getElementById('originalFileIcon'); | |
| originalFileIcon.className = 'fas mr-2'; | |
| originalFileIcon.classList.add(`fa-${originalIconClass}`, originalColorClass); | |
| // Set converted file info | |
| const convertedName = selectedFile.name.replace(/\.[^/.]+$/, '') + '.' + selectedFormat; | |
| document.getElementById('convertedFileName').textContent = convertedName; | |
| // Simulate a different file size | |
| const convertedSize = Math.max(selectedFile.size * 0.8, selectedFile.size * 1.2); | |
| document.getElementById('convertedFileSize').textContent = formatFileSize(convertedSize); | |
| document.getElementById('convertedFileType').textContent = selectedFormat.toUpperCase(); | |
| const convertedIconClass = fileIcons[selectedFormat] || fileIcons['default']; | |
| const convertedColorClass = fileColors[selectedFormat] || fileColors['default']; | |
| const convertedFileIcon = document.getElementById('convertedFileIcon'); | |
| convertedFileIcon.className = 'fas mr-2'; | |
| convertedFileIcon.classList.add(`fa-${convertedIconClass}`, convertedColorClass); | |
| } | |
| function resetConversion() { | |
| resultContainer.classList.add('hidden'); | |
| resetFileSelection(); | |
| formatBtns.forEach(b => b.classList.remove('border-blue-500', 'bg-blue-100')); | |
| selectedFormat = null; | |
| } | |
| function toggleAdvancedOptions() { | |
| advancedOptions.classList.toggle('hidden'); | |
| const icon = advancedToggle.querySelector('i'); | |
| icon.classList.toggle('rotate-180'); | |
| } | |
| function simulateDownload() { | |
| showToast('Đã bắt đầu tải xuống file chuyển đổi'); | |
| } | |
| function showShareOptions() { | |
| showToast('Chia sẻ file thành công'); | |
| } | |
| function showToast(message) { | |
| toastMessage.textContent = message; | |
| toast.classList.remove('hidden'); | |
| setTimeout(() => { | |
| toast.classList.add('hidden'); | |
| }, 3000); | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ninhdapchai/ninhmedia-com" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |