Spaces:
Running
Running
| <html lang="fa" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ورود با شیشه مایع</title> | |
| <!-- فونت وزیرمتن برای ظاهر فارسی زیبا --> | |
| <link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" /> | |
| <!-- آیکونهای FontAwesome --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --glass-bg: rgba(255, 255, 255, 0.05); | |
| --glass-border: rgba(255, 255, 255, 0.1); | |
| --glass-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); | |
| --primary-color: #0a84ff; | |
| --text-color: #ffffff; | |
| --text-muted: #a1a1aa; | |
| --error-color: #ff453a; | |
| --success-color: #30d158; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| outline: none; | |
| font-family: 'Vazirmatn', sans-serif; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body { | |
| background-color: #000; | |
| min-height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| overflow: hidden; | |
| position: relative; | |
| color: var(--text-color); | |
| } | |
| /* پسزمینه متحرک و گرادینت دارک */ | |
| .background-blobs { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: -1; | |
| overflow: hidden; | |
| } | |
| .blob { | |
| position: absolute; | |
| border-radius: 50%; | |
| filter: blur(80px); | |
| opacity: 0.6; | |
| animation: float 10s infinite ease-in-out; | |
| } | |
| .blob-1 { | |
| top: -10%; | |
| left: -10%; | |
| width: 50vw; | |
| height: 50vw; | |
| background: radial-gradient(circle, #4f2d7f, #000); | |
| animation-delay: 0s; | |
| } | |
| .blob-2 { | |
| bottom: -10%; | |
| right: -10%; | |
| width: 60vw; | |
| height: 60vw; | |
| background: radial-gradient(circle, #0f4c75, #000); | |
| animation-delay: -5s; | |
| } | |
| .blob-3 { | |
| top: 40%; | |
| left: 40%; | |
| width: 30vw; | |
| height: 30vw; | |
| background: radial-gradient(circle, #1a1a2e, #000); | |
| animation-duration: 15s; | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translate(0, 0) scale(1); } | |
| 50% { transform: translate(20px, -20px) scale(1.1); } | |
| } | |
| /* کانتینر اصلی شیشهای */ | |
| .login-container { | |
| width: 90%; | |
| max-width: 420px; | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| box-shadow: var(--glass-shadow); | |
| padding: 40px 30px; | |
| text-align: center; | |
| transition: height 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| /* هدر */ | |
| .header { | |
| margin-bottom: 30px; | |
| } | |
| .header h1 { | |
| font-size: 1.8rem; | |
| font-weight: 700; | |
| margin-bottom: 10px; | |
| background: linear-gradient(135deg, #fff 0%, #a5b4fc 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .header p { | |
| color: var(--text-muted); | |
| font-size: 0.9rem; | |
| } | |
| /* استایل فرمها و ورودیها */ | |
| .input-group { | |
| margin-bottom: 20px; | |
| position: relative; | |
| text-align: right; | |
| } | |
| .input-group i { | |
| position: absolute; | |
| top: 50%; | |
| right: 15px; | |
| transform: translateY(-50%); | |
| color: var(--text-muted); | |
| transition: color 0.3s; | |
| } | |
| .input-group input { | |
| width: 100%; | |
| background: rgba(0, 0, 0, 0.2); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 12px; | |
| padding: 14px 45px 14px 15px; | |
| color: #fff; | |
| font-size: 1rem; | |
| transition: all 0.3s ease; | |
| } | |
| .input-group input:focus { | |
| border-color: var(--primary-color); | |
| background: rgba(0, 0, 0, 0.4); | |
| box-shadow: 0 0 15px rgba(10, 132, 255, 0.2); | |
| } | |
| .input-group input:focus + i { | |
| color: var(--primary-color); | |
| } | |
| /* بخش کپچا */ | |
| .captcha-box { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| background: rgba(255, 255, 255, 0.03); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 12px; | |
| padding: 10px 15px; | |
| margin-bottom: 25px; | |
| } | |
| .captcha-question { | |
| font-size: 1.1rem; | |
| font-weight: bold; | |
| letter-spacing: 2px; | |
| user-select: none; | |
| color: #d1d5db; | |
| } | |
| .captcha-input { | |
| background: transparent; | |
| border: none; | |
| color: white; | |
| width: 60px; | |
| text-align: center; | |
| font-size: 1.1rem; | |
| border-bottom: 1px solid var(--glass-border); | |
| } | |
| .captcha-input:focus { | |
| border-bottom-color: var(--primary-color); | |
| } | |
| /* دکمهها */ | |
| .btn { | |
| width: 100%; | |
| padding: 14px; | |
| border: none; | |
| border-radius: 12px; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--primary-color), #0062cc); | |
| color: white; | |
| box-shadow: 0 4px 15px rgba(10, 132, 255, 0.3); | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(10, 132, 255, 0.4); | |
| } | |
| .btn-primary:active { | |
| transform: translateY(0); | |
| } | |
| .btn-primary:disabled { | |
| background: #333; | |
| color: #666; | |
| cursor: not-allowed; | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .btn-link { | |
| background: transparent; | |
| color: var(--text-muted); | |
| margin-top: 15px; | |
| font-size: 0.9rem; | |
| } | |
| .btn-link:hover { | |
| color: white; | |
| text-decoration: underline; | |
| } | |
| /* مدیریت مراحل (Steps) */ | |
| .step { | |
| display: none; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| .step.active { | |
| display: block; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* تایمر ارسال مجدد کد */ | |
| .timer-text { | |
| font-size: 0.85rem; | |
| color: var(--text-muted); | |
| margin-top: 15px; | |
| min-height: 20px; | |
| } | |
| .timer-text span { | |
| color: var(--primary-color); | |
| font-weight: bold; | |
| } | |
| /* صفحه موفقیت */ | |
| .success-icon { | |
| font-size: 4rem; | |
| color: var(--success-color); | |
| margin-bottom: 20px; | |
| animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); | |
| } | |
| @keyframes popIn { | |
| 0% { transform: scale(0); } | |
| 80% { transform: scale(1.2); } | |
| 100% { transform: scale(1); } | |
| } | |
| /* Toast Notification */ | |
| .toast-container { | |
| position: fixed; | |
| top: 20px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| z-index: 1000; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .toast { | |
| background: rgba(20, 20, 20, 0.9); | |
| backdrop-filter: blur(10px); | |
| color: white; | |
| padding: 12px 24px; | |
| border-radius: 50px; | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.5); | |
| border: 1px solid var(--glass-border); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-size: 0.9rem; | |
| opacity: 0; | |
| transform: translateY(-20px); | |
| transition: all 0.3s ease; | |
| } | |
| .toast.show { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| .toast.error i { color: var(--error-color); } | |
| .toast.success i { color: var(--success-color); } | |
| .toast.info i { color: var(--primary-color); } | |
| /* لینک اجباری AnyCoder */ | |
| .anycoder-link { | |
| position: absolute; | |
| top: 15px; | |
| left: 15px; | |
| font-size: 0.8rem; | |
| color: rgba(255, 255, 255, 0.3); | |
| text-decoration: none; | |
| transition: color 0.3s; | |
| z-index: 10; | |
| } | |
| .anycoder-link:hover { | |
| color: var(--primary-color); | |
| } | |
| /* ریسپانسیو */ | |
| @media (max-width: 480px) { | |
| .login-container { | |
| width: 95%; | |
| padding: 30px 20px; | |
| } | |
| .header h1 { | |
| font-size: 1.5rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- لینک اجباری --> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> | |
| Built with anycoder | |
| </a> | |
| <!-- پسزمینه متحرک --> | |
| <div class="background-blobs"> | |
| <div class="blob blob-1"></div> | |
| <div class="blob blob-2"></div> | |
| <div class="blob blob-3"></div> | |
| </div> | |
| <!-- کانتینر اعلانها --> | |
| <div class="toast-container" id="toastContainer"></div> | |
| <!-- کارت اصلی لاگین --> | |
| <main class="login-container"> | |
| <!-- مرحله ۱: ورود شماره موبایل و کپچا --> | |
| <div id="step1" class="step active"> | |
| <header class="header"> | |
| <div class="icon-circle" style="font-size: 2.5rem; margin-bottom: 15px; color: var(--primary-color);"> | |
| <i class="fa-solid fa-user-astronaut"></i> | |
| </div> | |
| <h1>خوش آمدید</h1> | |
| <p>برای ادامه شماره موبایل خود را وارد کنید</p> | |
| </header> | |
| <form id="phoneForm" onsubmit="handleSendCode(event)"> | |
| <div class="input-group"> | |
| <i class="fa-solid fa-mobile-screen"></i> | |
| <input type="tel" id="phoneInput" placeholder="شماره موبایل (مثال: 09123456789)" maxlength="11" autocomplete="off"> | |
| </div> | |
| <!-- کپچا ساده --> | |
| <div class="captcha-box"> | |
| <span class="captcha-question" id="captchaQuestion">5 + 3 = ?</span> | |
| <input type="number" id="captchaInput" class="captcha-input" placeholder="?" autocomplete="off"> | |
| </div> | |
| <button type="submit" class="btn btn-primary" id="sendCodeBtn"> | |
| <span>دریافت کد تایید</span> | |
| <i class="fa-solid fa-arrow-left"></i> | |
| </button> | |
| </form> | |
| </div> | |
| <!-- مرحله ۲: تایید کد --> | |
| <div id="step2" class="step"> | |
| <header class="header"> | |
| <div style="font-size: 2.5rem; margin-bottom: 15px; color: var(--primary-color);"> | |
| <i class="fa-solid fa-shield-halved"></i> | |
| </div> | |
| <h1>تایید شماره</h1> | |
| <p>کد ارسال شده به <span id="displayPhone" style="color: white; direction: ltr;"></span> را وارد کنید</p> | |
| </header> | |
| <form id="otpForm" onsubmit="handleVerifyCode(event)"> | |
| <div class="input-group"> | |
| <i class="fa-solid fa-key"></i> | |
| <input type="tel" id="otpInput" placeholder="کد ۵ رقمی" maxlength="5" inputmode="numeric" autocomplete="one-time-code"> | |
| </div> | |
| <button type="submit" class="btn btn-primary" id="verifyBtn"> | |
| <span>تایید و ورود</span> | |
| <i class="fa-solid fa-check"></i> | |
| </button> | |
| </form> | |
| <div class="timer-text" id="timerArea"> | |
| ارسال مجدد کد تا <span id="timerCount">120</span> ثانیه دیگر امکانپذیر است. | |
| </div> | |
| <button class="btn btn-link" id="resendBtn" onclick="resendCode()" style="display: none;"> | |
| ارسال مجدد کد تایید | |
| </button> | |
| <button class="btn btn-link" onclick="goBack()"> | |
| <i class="fa-solid fa-arrow-right"></i> تغییر شماره | |
| </button> | |
| </div> | |
| <!-- مرحله ۳: ورود موفق --> | |
| <div id="step3" class="step"> | |
| <div class="success-icon"> | |
| <i class="fa-solid fa-circle-check"></i> | |
| </div> | |
| <h1>ورود موفقیتآمیز!</h1> | |
| <p style="margin-bottom: 30px; color: var(--text-muted);">شما با موفقیت احراز هویت شدید.</p> | |
| <button class="btn btn-primary" onclick="window.location.reload()"> | |
| <span>بازگشت به خانه</span> | |
| <i class="fa-solid fa-house"></i> | |
| </button> | |
| </div> | |
| </main> | |
| <script> | |
| // --- متغیرهای وضعیت --- | |
| let currentCaptchaAnswer = 0; | |
| let countdownInterval; | |
| const RESEND_TIME = 120; // 2 دقیقه به ثانیه | |
| // --- المانهای DOM --- | |
| const steps = { | |
| 1: document.getElementById('step1'), | |
| 2: document.getElementById('step2'), | |
| 3: document.getElementById('step3') | |
| }; | |
| const phoneInput = document.getElementById('phoneInput'); | |
| const captchaQuestion = document.getElementById('captchaQuestion'); | |
| const captchaInput = document.getElementById('captchaInput'); | |
| const displayPhone = document.getElementById('displayPhone'); | |
| const otpInput = document.getElementById('otpInput'); | |
| const timerArea = document.getElementById('timerArea'); | |
| const timerCount = document.getElementById('timerCount'); | |
| const resendBtn = document.getElementById('resendBtn'); | |
| // --- راهاندازی اولیه --- | |
| window.onload = () => { | |
| generateCaptcha(); | |
| }; | |
| // --- توابع کمکی --- | |
| // نمایش اعلان (Toast) | |
| function showToast(message, type = 'info') { | |
| const container = document.getElementById('toastContainer'); | |
| const toast = document.createElement('div'); | |
| toast.className = `toast ${type}`; | |
| let iconClass = 'fa-circle-info'; | |
| if (type === 'error') iconClass = 'fa-circle-xmark'; | |
| if (type === 'success') iconClass = 'fa-circle-check'; | |
| toast.innerHTML = `<i class="fa-solid ${iconClass}"></i> <span>${message}</span>`; | |
| container.appendChild(toast); | |
| // انیمیشن ورود | |
| requestAnimationFrame(() => { | |
| toast.classList.add('show'); | |
| }); | |
| // حذف خودکار | |
| setTimeout(() => { | |
| toast.classList.remove('show'); | |
| setTimeout(() => toast.remove(), 300); | |
| }, 3000); | |
| } | |
| // تولید کپچای ریاضی | |
| function generateCaptcha() { | |
| const num1 = Math.floor(Math.random() * 10); | |
| const num2 = Math.floor(Math.random() * 10); | |
| currentCaptchaAnswer = num1 + num2; | |
| captchaQuestion.innerText = `${num1} + ${num2} = ?`; | |
| captchaInput.value = ''; | |
| } | |
| // اعتبارسنجی شماره موبایل ایران | |
| function isValidPhone(phone) { | |
| const regex = /^09[0-9]{9}$/; | |
| return regex.test(phone); | |
| } | |
| // تغییر مراحل | |
| function showStep(stepNumber) { | |
| Object.values(steps).forEach(el => el.classList.remove('active')); | |
| steps[stepNumber].classList.add('active'); | |
| } | |
| // --- منطق اصلی --- | |
| // هندل کردن ارسال کد (مرحله 1) | |
| function handleSendCode(e) { | |
| e.preventDefault(); | |
| const phone = phoneInput.value.trim(); | |
| const captchaUserAnswer = parseInt(captchaInput.value); | |
| // 1. اعتبارسنجی شماره | |
| if (!isValidPhone(phone)) { | |
| showToast('لطفاً شماره موبایل معتبر وارد کنید (با 09 شروع شود)', 'error'); | |
| phoneInput.focus(); | |
| return; | |
| } | |
| // 2. اعتبارسنجی کپچا | |
| if (isNaN(captchaUserAnswer) || captchaUserAnswer !== currentCaptchaAnswer) { | |
| showToast('جمع صحیح نیست!', 'error'); | |
| captchaInput.value = ''; | |
| generateCaptcha(); // ریست کردن کپچا برای امنیت بیشتر | |
| captchaInput.focus(); | |
| return; | |
| } | |
| // موفقیت آمیز بودن - شبیهسازی ارسال کد | |
| displayPhone.innerText = phone; | |
| showToast('کد تایید ارسال شد (کد تست: 12345)', 'success'); | |
| // شروع تایمر | |
| startTimer(); | |
| // انتقال به مرحله بعد | |
| showStep(2); | |
| otpInput.focus(); | |
| } | |
| // هندل کردن تایید کد (مرحله 2) | |
| function handleVerifyCode(e) { | |
| e.preventDefault(); | |
| const code = otpInput.value.trim(); | |
| if (code.length < 4) { | |
| showToast('کد تایید نامعتبر است', 'error'); | |
| return; | |
| } | |
| // شبیهسازی بررسی کد (در اینجا هر کد 5 رقمی یا کد خاصی قبول میشود) | |
| // برای دمو، کد 12345 یا هر چیز 5 رقمی قبول میکنیم | |
| if (code === '12345' || code.length === 5) { | |
| showToast('در حال ورود...', 'info'); | |
| // تاخیر مصنوعی برای حس واقعی بودن | |
| setTimeout(() => { | |
| showStep(3); | |
| }, 1000); | |
| } else { | |
| showToast('کد اشتباه است. دوباره تلاش کنید.', 'error'); | |
| } | |
| } | |
| // تایمر شمارش معکوس (2 دقیقه) | |
| function startTimer() { | |
| let timeLeft = RESEND_TIME; | |
| // نمایش تایمر و مخفی کردن دکمه ارسال مجدد | |
| timerArea.style.display = 'block'; | |
| resendBtn.style.display = 'none'; | |
| timerCount.innerText = timeLeft; | |
| // پاک کردن تایمر قبلی اگر وجود دارد | |
| if (countdownInterval) clearInterval(countdownInterval); | |
| countdownInterval = setInterval(() => { | |
| timeLeft--; | |
| timerCount.innerText = timeLeft; | |
| if (timeLeft <= 0) { | |
| clearInterval(countdownInterval); | |
| timerArea.style.display = 'none'; // مخفی کردن متن تایمر | |
| resendBtn.style.display = 'inline-block'; // نمایش دکمه ارسال مجدد | |
| showToast('اکنون میتوانید کد جدید بگیرید', 'info'); | |
| } | |
| }, 1000); | |
| } | |
| // ارسال مجدد کد | |
| function resendCode() { | |
| const phone = phoneInput.value.trim(); | |
| if (!isValidPhone(phone)) return; | |
| showToast('کد تایید جدید ارسال شد', 'success'); | |
| otpInput.value = ''; // پاک کردن ورودی قبلی | |
| otpInput.focus(); | |
| startTimer(); // شروع مجدد تایمر | |
| } | |
| // بازگشت به مرحله قبل | |
| function goBack() { | |
| showStep(1); | |
| // پاک کردن تایمر زمانی که کاربر برمیگردد تا منابع مصرف نشوند | |
| if (countdownInterval) clearInterval(countdownInterval); | |
| } | |
| // فرمت خودکار ورودی شماره موبایل (فقط عدد) | |
| phoneInput.addEventListener('input', function(e) { | |
| this.value = this.value.replace(/[^0-9]/g, ''); | |
| }); | |
| // فرمت خودکار ورودی کپچا | |
| captchaInput.addEventListener('input', function(e) { | |
| this.value = this.value.replace(/[^0-9]/g, ''); | |
| }); | |
| // فرمت خودکار ورودی کد تایید | |
| otpInput.addEventListener('input', function(e) { | |
| this.value = this.value.replace(/[^0-9]/g, ''); | |
| }); | |
| </script> | |
| </body> | |
| </html> |