Files
XiangYue/js/web.js
风之暇想 bcc6329cee v1.1
2025-07-16 19:10:25 +08:00

13 lines
8.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function showNotification(message,isSuccess=true){const notificationContainer=document.createElement('div');notificationContainer.className='fixed right-4 transition-all duration-300 ease-in-out translate-x-full z-50';const navHeight=document.querySelector('nav')?.offsetHeight||0;notificationContainer.style.top=`${navHeight + 10}px`;const setNotificationWidth=()=>{notificationContainer.style.width=window.innerWidth<640 ? '90%':'280px';};setNotificationWidth();const isDarkMode=document.documentElement.classList.contains('dark');const baseClass=`bg-white rounded-lg shadow-lg p-3 flex items-start ${isSuccess ? 'border-l-4 border-green-500' : 'border-l-4 border-red-500'}`;const darkClass=`bg-gray-800 border-gray-700 text-white`;const finalClass=isDarkMode ? `${baseClass} ${darkClass}`:baseClass;notificationContainer.innerHTML=`
<div class="${finalClass}">
<div class="flex-shrink-0 mt-0.5 mr-2 ${isSuccess ? 'text-green-500' : 'text-red-500'}">
<i class="fa-solid fa-${isSuccess ? 'check' : 'exclamation'}-circle"></i>
</div>
<div class="max-w-[90%]">
<p class="text-sm font-medium text-gray-800 dark:text-white">${message}</p>
</div>
<button class="ml-auto flex-shrink-0 inline-flex text-gray-400 hover:text-gray-600 focus:outline-none" onclick="this.parentElement.parentElement.remove()">
<i class="fa-solid fa-times"></i>
</button>
</div>
`;document.body.appendChild(notificationContainer);setTimeout(()=>{notificationContainer.classList.remove('translate-x-full');},10);const removeNotification=()=>{notificationContainer.classList.add('translate-x-full');setTimeout(()=>{notificationContainer.remove();},300);};const timeoutId=setTimeout(removeNotification,5000);notificationContainer.querySelector('button').addEventListener('click',()=>{clearTimeout(timeoutId);removeNotification();});window.addEventListener('resize',setNotificationWidth);return notificationContainer;}function updateNotificationStyle(notificationContainer){const isDarkMode=document.documentElement.classList.contains('dark');const baseClass=`bg-white rounded-lg shadow-lg p-3 flex items-start ${notificationContainer.querySelector('div').classList.contains('border-l-4.border-green-500') ? 'border-l-4 border-green-500' : 'border-l-4 border-red-500'}`;const darkClass=`bg-gray-800 border-gray-700 text-white`;const finalClass=isDarkMode ? `${baseClass} ${darkClass}`:baseClass;notificationContainer.querySelector('div').className=finalClass;}document.addEventListener('DOMContentLoaded',()=>{const elements={textInput:document.getElementById('text-input'),resultOutput:document.getElementById('result-output'),encryptionKey:document.getElementById('encryption-key'),encryptBtn:document.getElementById('encrypt-btn'),decryptBtn:document.getElementById('decrypt-btn'),copyBtn:document.getElementById('copy-btn'),clearBtn:document.getElementById('clear-btn'),toggleKeyVisibility:document.getElementById('toggle-key-visibility'),generatePassword:document.getElementById('generate-password'),resultStatus:document.getElementById('result-status'),themeToggle:document.getElementById('theme-toggle'),base64Toggle:document.getElementById('base64-toggle'),pasteBtn:document.getElementById('paste-btn')};const isDarkMode=localStorage.theme==='dark'||(!('theme' in localStorage)&&window.matchMedia('(prefers-color-scheme: dark)').matches);if(isDarkMode){document.documentElement.classList.add('dark');elements.themeToggle.innerHTML='<i class="fa-solid fa-moon text-white"></i>';}const checkBrowserSupport=()=>{const requiredAPIs=[{api:window.crypto.subtle,message:'当前浏览器不支持Web Crypto API无法使用加密功能'},{api:window.CompressionStream&&window.DecompressionStream,message:'当前浏览器不支持压缩/解压缩API无法使用加密功能'}];for(const{api,message}of requiredAPIs){if(!api){showNotification(message,false);elements.encryptBtn.disabled=true;elements.decryptBtn.disabled=true;return false;}}try{new CompressionStream('deflate');new DecompressionStream('deflate');return true;}catch(e){showNotification('当前浏览器不支持Deflate压缩算法无法使用加密功能',false);elements.encryptBtn.disabled=true;elements.decryptBtn.disabled=true;return false;}};checkBrowserSupport();elements.generatePassword.addEventListener('click',()=>{const password=utils.generatePassword(25);elements.encryptionKey.value=password;utils.copyToClipboard(password);showNotification('已生成并复制25位随机密码');});elements.toggleKeyVisibility.addEventListener('click',()=>{const type=elements.encryptionKey.getAttribute('type')==='password' ? 'text':'password';elements.encryptionKey.setAttribute('type',type);elements.toggleKeyVisibility.innerHTML=`<i class="fa-regular fa-${type === 'password' ? 'eye-slash' : 'eye'}"></i>`;});let outputMode='chinese';elements.base64Toggle.addEventListener('click',()=>{switch(outputMode){case 'chinese':outputMode='base64';break;case 'base64':outputMode='emoji';break;case 'emoji':outputMode='chinese';break;}const icons={chinese:'language',base64:'code',emoji:'smile'};elements.base64Toggle.innerHTML=`<i class="fa-solid fa-${icons[outputMode]} theme-toggle-icon"></i>`;showNotification(`已切换到 ${outputMode === 'chinese' ? '中文' : outputMode === 'base64' ? 'Base64' : 'Emoji'} 模式`);});elements.pasteBtn.addEventListener('click',async()=>{try{const clipboardText=await navigator.clipboard.readText();elements.textInput.value=clipboardText;showNotification('已从剪贴板粘贴文本');}catch(error){showNotification('无法从剪贴板粘贴文本',false);}});const handleEncryptionDecryption=async(action,inputText,password,isDefaultPassword)=>{try{elements.resultStatus.textContent=`${action}中......`;elements.resultStatus.className='absolute top-3 right-3 px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200';elements.resultStatus.classList.remove('hidden');const result=action==='加密' ? await encryptionMethod1.encrypt(inputText,password,outputMode):await encryptionMethod1.decrypt(inputText,password);elements.resultOutput.value=result;elements.resultStatus.textContent=`${action}成功`;elements.resultStatus.className='absolute top-3 right-3 px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';if(isDefaultPassword){showNotification(`未检测到密码,使用默认密码${action},建议更换为安全的密码。`,true);}else{showNotification(`文本已成功${action}`);}}catch(error){elements.resultOutput.value='';elements.resultStatus.textContent=`${action}失败`;elements.resultStatus.className='absolute top-3 right-3 px-2 py-1 rounded-full text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';elements.resultStatus.classList.remove('hidden');showNotification(error.message,false);}};elements.encryptBtn.addEventListener('click',async()=>{const plaintext=elements.textInput.value;let password=elements.encryptionKey.value.trim();let isDefaultPassword=false;if(!plaintext)return showNotification('请输入要加密的文本',false);if(!password){password=DEFAULT_PASSWORD;isDefaultPassword=true;}await handleEncryptionDecryption('加密',plaintext,password,isDefaultPassword);});elements.decryptBtn.addEventListener('click',async()=>{const ciphertext=elements.textInput.value.trim();let password=elements.encryptionKey.value.trim();let isDefaultPassword=false;if(!ciphertext)return showNotification('请输入要解密的文本',false);if(!password){password=DEFAULT_PASSWORD;isDefaultPassword=true;}const detectedMode=utils.detectCiphertextType(ciphertext);showNotification(`已识别密文类型: ${detectedMode === 'chinese' ? '中文' : detectedMode === 'base64' ? 'Base64' : 'Emoji'}`);await handleEncryptionDecryption('解密',ciphertext,password,isDefaultPassword);});elements.copyBtn.addEventListener('click',()=>{const result=elements.resultOutput.value;if(!result)return showNotification('没有可复制的结果',false);utils.copyToClipboard(result);showNotification('结果已复制到剪贴板');});elements.clearBtn.addEventListener('click',()=>{elements.textInput.value='';elements.resultOutput.value='';elements.encryptionKey.value='';elements.resultStatus.classList.add('hidden');showNotification('已清空所有内容');});elements.themeToggle.addEventListener('click',()=>{const isDark=document.documentElement.classList.toggle('dark');localStorage.theme=isDark ? 'dark':'light';elements.themeToggle.innerHTML=`<i class="fa-solid fa-${isDark ? 'moon' : 'sun'} text-${isDark ? 'white' : 'dark'}"></i>`;const notifications=document.querySelectorAll('.fixed.right-4.transition-all.duration-300.ease-in-out.z-50');notifications.forEach(notification=>{updateNotificationStyle(notification);});});});