| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>京东抢购助手 - 带扫码登录</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> |
| .countdown { |
| font-family: 'Arial', sans-serif; |
| font-size: 2rem; |
| font-weight: bold; |
| color: #e1251b; |
| text-align: center; |
| margin: 20px 0; |
| } |
| |
| .progress-bar { |
| height: 10px; |
| background-color: #f0f0f0; |
| border-radius: 5px; |
| overflow: hidden; |
| margin: 15px 0; |
| } |
| |
| .progress { |
| height: 100%; |
| background-color: #e1251b; |
| width: 0%; |
| transition: width 0.3s ease; |
| } |
| |
| .flashing { |
| animation: flash 1s infinite; |
| } |
| |
| @keyframes flash { |
| 0% { opacity: 1; } |
| 50% { opacity: 0.5; } |
| 100% { opacity: 1; } |
| } |
| |
| .status-badge { |
| display: inline-block; |
| padding: 3px 8px; |
| border-radius: 12px; |
| font-size: 12px; |
| font-weight: bold; |
| } |
| |
| .status-waiting { |
| background-color: #f0ad4e; |
| color: white; |
| } |
| |
| .status-ready { |
| background-color: #5cb85c; |
| color: white; |
| } |
| |
| .status-active { |
| background-color: #e1251b; |
| color: white; |
| animation: pulse 1s infinite; |
| } |
| |
| @keyframes pulse { |
| 0% { transform: scale(1); } |
| 50% { transform: scale(1.05); } |
| 100% { transform: scale(1); } |
| } |
| |
| .log-entry { |
| padding: 8px 12px; |
| border-bottom: 1px solid #eee; |
| font-size: 13px; |
| font-family: monospace; |
| } |
| |
| .log-time { |
| color: #999; |
| margin-right: 10px; |
| } |
| |
| .log-info { |
| color: #31708f; |
| } |
| |
| .log-warning { |
| color: #8a6d3b; |
| } |
| |
| .log-error { |
| color: #a94442; |
| } |
| |
| .log-success { |
| color: #3c763d; |
| } |
| |
| .qr-code-container { |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| padding: 20px; |
| background: white; |
| border-radius: 8px; |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); |
| margin: 20px 0; |
| } |
| |
| .qr-code { |
| width: 200px; |
| height: 200px; |
| margin-bottom: 15px; |
| background: white; |
| padding: 10px; |
| border: 1px solid #eee; |
| } |
| |
| .modal { |
| display: none; |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| background-color: rgba(0, 0, 0, 0.5); |
| z-index: 1000; |
| justify-content: center; |
| align-items: center; |
| } |
| |
| .modal-content { |
| background: white; |
| border-radius: 8px; |
| width: 90%; |
| max-width: 400px; |
| overflow: hidden; |
| } |
| |
| .modal-header { |
| padding: 15px; |
| background: #f8f9fa; |
| border-bottom: 1px solid #eee; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| } |
| |
| .modal-body { |
| padding: 20px; |
| } |
| |
| .modal-footer { |
| padding: 15px; |
| background: #f8f9fa; |
| border-top: 1px solid #eee; |
| display: flex; |
| justify-content: flex-end; |
| } |
| |
| .login-status { |
| display: flex; |
| align-items: center; |
| padding: 8px 12px; |
| border-radius: 20px; |
| font-size: 14px; |
| margin-bottom: 15px; |
| } |
| |
| .login-status.not-logged { |
| background-color: #f8d7da; |
| color: #721c24; |
| } |
| |
| .login-status.logged { |
| background-color: #d4edda; |
| color: #155724; |
| } |
| |
| .user-avatar { |
| width: 40px; |
| height: 40px; |
| border-radius: 50%; |
| margin-right: 10px; |
| object-fit: cover; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50 min-h-screen"> |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> |
| <header class="mb-8 text-center"> |
| <h1 class="text-3xl font-bold text-red-600 mb-2"> |
| <i class="fas fa-bolt mr-2"></i>京东抢购助手 |
| </h1> |
| <p class="text-gray-600">带扫码登录功能的定时自动抢购工具</p> |
| </header> |
|
|
| |
| <div class="bg-white rounded-lg shadow-md p-6 mb-8"> |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2"> |
| <i class="fas fa-user mr-2"></i>账号状态 |
| </h2> |
| |
| <div id="login-status" class="login-status not-logged"> |
| <i class="fas fa-exclamation-circle mr-2"></i> |
| <span>未登录京东账号</span> |
| </div> |
| |
| <div class="flex justify-center"> |
| <button id="login-btn" class="px-6 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700"> |
| <i class="fas fa-sign-in-alt mr-2"></i>扫码登录京东 |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-lg shadow-md p-6 mb-8"> |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> |
| |
| <div> |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2"> |
| <i class="fas fa-shopping-cart mr-2"></i>商品信息 |
| </h2> |
| |
| <div class="mb-4"> |
| <label for="product-url" class="block text-sm font-medium text-gray-700 mb-1">商品链接</label> |
| <input type="text" id="product-url" placeholder="https://item.jd.com/商品ID.html" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-red-500 focus:border-red-500"> |
| </div> |
| |
| <div class="mb-4"> |
| <label for="product-name" class="block text-sm font-medium text-gray-700 mb-1">商品名称</label> |
| <input type="text" id="product-name" placeholder="商品名称(可选)" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-red-500 focus:border-red-500"> |
| </div> |
| |
| <div class="mb-4"> |
| <label for="product-image" class="block text-sm font-medium text-gray-700 mb-1">商品图片</label> |
| <div class="flex items-center"> |
| <div id="product-image-preview" class="w-16 h-16 bg-gray-200 rounded mr-3 flex items-center justify-center"> |
| <i class="fas fa-image text-gray-400"></i> |
| </div> |
| <input type="text" id="product-image" placeholder="图片URL(可选)" |
| class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-red-500 focus:border-red-500"> |
| </div> |
| </div> |
| |
| <div class="mb-4"> |
| <label for="product-price" class="block text-sm font-medium text-gray-700 mb-1">秒杀价格</label> |
| <div class="relative"> |
| <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> |
| <span class="text-gray-500">¥</span> |
| </div> |
| <input type="number" id="product-price" placeholder="0.00" |
| class="pl-8 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-red-500 focus:border-red-500"> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div> |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2"> |
| <i class="fas fa-clock mr-2"></i>抢购设置 |
| </h2> |
| |
| <div class="mb-4"> |
| <label for="buy-time" class="block text-sm font-medium text-gray-700 mb-1">抢购时间</label> |
| <input type="datetime-local" id="buy-time" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-red-500 focus:border-red-500"> |
| </div> |
| |
| <div class="mb-4"> |
| <label for="buy-quantity" class="block text-sm font-medium text-gray-700 mb-1">购买数量</label> |
| <div class="flex items-center"> |
| <button id="quantity-minus" class="px-3 py-1 bg-gray-200 rounded-l-lg hover:bg-gray-300"> |
| <i class="fas fa-minus"></i> |
| </button> |
| <input type="number" id="buy-quantity" value="1" min="1" max="99" |
| class="w-16 text-center px-2 py-1 border-t border-b border-gray-300"> |
| <button id="quantity-plus" class="px-3 py-1 bg-gray-200 rounded-r-lg hover:bg-gray-300"> |
| <i class="fas fa-plus"></i> |
| </button> |
| </div> |
| </div> |
| |
| <div class="mb-4"> |
| <label class="block text-sm font-medium text-gray-700 mb-1">抢购策略</label> |
| <div class="space-y-2"> |
| <label class="flex items-center"> |
| <input type="radio" name="strategy" value="precise" checked class="text-red-600"> |
| <span class="ml-2">精确时间(推荐)</span> |
| </label> |
| <label class="flex items-center"> |
| <input type="radio" name="strategy" value="early" class="text-red-600"> |
| <span class="ml-2">提前1秒(防网络延迟)</span> |
| </label> |
| <label class="flex items-center"> |
| <input type="radio" name="strategy" value="random" class="text-red-600"> |
| <span class="ml-2">随机提前0.5-1.5秒</span> |
| </label> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="mt-6 p-4 bg-gray-50 rounded-lg"> |
| <div class="flex items-center justify-between mb-2"> |
| <div> |
| <span id="current-status" class="status-badge status-waiting">等待配置</span> |
| <span id="product-display" class="ml-3 text-gray-700">未设置商品</span> |
| </div> |
| <div id="countdown-display" class="countdown">--:--:--</div> |
| </div> |
| |
| <div class="progress-bar"> |
| <div id="progress" class="progress"></div> |
| </div> |
| |
| <div class="flex justify-center mt-4"> |
| <button id="start-btn" class="px-6 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 mr-4"> |
| <i class="fas fa-play mr-2"></i>开始抢购 |
| </button> |
| <button id="stop-btn" class="px-6 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600" disabled> |
| <i class="fas fa-stop mr-2"></i>停止 |
| </button> |
| <button id="test-btn" class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 ml-4"> |
| <i class="fas fa-vial mr-2"></i>测试 |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="bg-white rounded-lg shadow-md p-6"> |
| <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2"> |
| <i class="fas fa-terminal mr-2"></i>操作日志 |
| </h2> |
| |
| <div class="flex justify-between mb-4"> |
| <div> |
| <button id="clear-log-btn" class="px-3 py-1 bg-gray-200 text-gray-700 rounded hover:bg-gray-300 text-sm"> |
| <i class="fas fa-trash-alt mr-1"></i>清空日志 |
| </button> |
| </div> |
| <div class="text-sm text-gray-500"> |
| <span id="log-count">0</span> 条记录 |
| </div> |
| </div> |
| |
| <div id="log-container" class="border rounded-lg overflow-hidden" style="max-height: 300px; overflow-y: auto;"> |
| <div class="text-center py-4 text-gray-500" id="empty-log"> |
| <i class="fas fa-info-circle mr-2"></i>暂无日志记录 |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="login-modal" class="modal"> |
| <div class="modal-content"> |
| <div class="modal-header"> |
| <h3 class="text-lg font-semibold">京东账号登录</h3> |
| <button id="close-modal" class="text-gray-500 hover:text-gray-700"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="modal-body"> |
| <div class="qr-code-container"> |
| <div class="qr-code" id="qr-code"> |
| |
| <div class="flex flex-col items-center justify-center h-full"> |
| <i class="fas fa-qrcode text-4xl text-gray-400 mb-2"></i> |
| <p class="text-sm text-gray-500">加载二维码中...</p> |
| </div> |
| </div> |
| <p class="text-sm text-gray-600">使用京东APP扫描二维码登录</p> |
| <div class="mt-4 text-center"> |
| <div id="qr-status" class="text-sm text-gray-600"> |
| <i class="fas fa-sync-alt fa-spin mr-2"></i>等待扫描... |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="modal-footer"> |
| <button id="refresh-qr" class="px-4 py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300 mr-2"> |
| <i class="fas fa-sync-alt mr-2"></i>刷新二维码 |
| </button> |
| <button id="cancel-login" class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600"> |
| 取消 |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| let countdownInterval = null; |
| let buyTimeout = null; |
| let isRunning = false; |
| let testMode = false; |
| let logEntries = 0; |
| let isLoggedIn = false; |
| let userInfo = null; |
| let qrRefreshInterval = null; |
| |
| |
| const productUrlInput = document.getElementById('product-url'); |
| const productNameInput = document.getElementById('product-name'); |
| const productImageInput = document.getElementById('product-image'); |
| const productImagePreview = document.getElementById('product-image-preview'); |
| const productPriceInput = document.getElementById('product-price'); |
| const buyTimeInput = document.getElementById('buy-time'); |
| const buyQuantityInput = document.getElementById('buy-quantity'); |
| const quantityMinusBtn = document.getElementById('quantity-minus'); |
| const quantityPlusBtn = document.getElementById('quantity-plus'); |
| const startBtn = document.getElementById('start-btn'); |
| const stopBtn = document.getElementById('stop-btn'); |
| const testBtn = document.getElementById('test-btn'); |
| const clearLogBtn = document.getElementById('clear-log-btn'); |
| const currentStatus = document.getElementById('current-status'); |
| const productDisplay = document.getElementById('product-display'); |
| const countdownDisplay = document.getElementById('countdown-display'); |
| const progressBar = document.getElementById('progress'); |
| const logContainer = document.getElementById('log-container'); |
| const emptyLog = document.getElementById('empty-log'); |
| const logCount = document.getElementById('log-count'); |
| const loginBtn = document.getElementById('login-btn'); |
| const loginModal = document.getElementById('login-modal'); |
| const closeModalBtn = document.getElementById('close-modal'); |
| const qrCodeElement = document.getElementById('qr-code'); |
| const qrStatusElement = document.getElementById('qr-status'); |
| const refreshQrBtn = document.getElementById('refresh-qr'); |
| const cancelLoginBtn = document.getElementById('cancel-login'); |
| const loginStatusElement = document.getElementById('login-status'); |
| |
| |
| const now = new Date(); |
| now.setMinutes(now.getMinutes() + 5); |
| buyTimeInput.value = formatDateTimeInput(now); |
| |
| |
| productUrlInput.addEventListener('change', updateProductDisplay); |
| productNameInput.addEventListener('change', updateProductDisplay); |
| productImageInput.addEventListener('change', updateProductImage); |
| quantityMinusBtn.addEventListener('click', decreaseQuantity); |
| quantityPlusBtn.addEventListener('click', increaseQuantity); |
| startBtn.addEventListener('click', startCountdown); |
| stopBtn.addEventListener('click', stopCountdown); |
| testBtn.addEventListener('click', testModeToggle); |
| clearLogBtn.addEventListener('click', clearLog); |
| loginBtn.addEventListener('click', showLoginModal); |
| closeModalBtn.addEventListener('click', hideLoginModal); |
| refreshQrBtn.addEventListener('click', generateQRCode); |
| cancelLoginBtn.addEventListener('click', hideLoginModal); |
| |
| |
| function updateProductImage() { |
| const imageUrl = productImageInput.value.trim(); |
| if (imageUrl) { |
| productImagePreview.innerHTML = `<img src="${imageUrl}" class="w-full h-full object-cover rounded">`; |
| } else { |
| productImagePreview.innerHTML = '<i class="fas fa-image text-gray-400"></i>'; |
| } |
| } |
| |
| |
| function updateProductDisplay() { |
| const url = productUrlInput.value.trim(); |
| const name = productNameInput.value.trim(); |
| |
| if (url) { |
| |
| const match = url.match(/jd\.com\/(\d+)\.html/); |
| const productId = match ? match[1] : '未知商品'; |
| |
| if (name) { |
| productDisplay.textContent = `${name} (${productId})`; |
| } else { |
| productDisplay.textContent = `京东商品 ${productId}`; |
| } |
| |
| currentStatus.className = 'status-badge status-ready'; |
| currentStatus.textContent = '准备就绪'; |
| } else { |
| productDisplay.textContent = '未设置商品'; |
| currentStatus.className = 'status-badge status-waiting'; |
| currentStatus.textContent = '等待配置'; |
| } |
| } |
| |
| |
| function decreaseQuantity() { |
| let value = parseInt(buyQuantityInput.value); |
| if (value > 1) { |
| buyQuantityInput.value = value - 1; |
| } |
| } |
| |
| function increaseQuantity() { |
| let value = parseInt(buyQuantityInput.value); |
| if (value < 99) { |
| buyQuantityInput.value = value + 1; |
| } |
| } |
| |
| |
| function startCountdown() { |
| |
| if (!isLoggedIn) { |
| addLog('请先登录京东账号', 'error'); |
| showLoginModal(); |
| return; |
| } |
| |
| |
| if (!productUrlInput.value.trim()) { |
| addLog('请填写商品链接', 'error'); |
| return; |
| } |
| |
| const buyTime = new Date(buyTimeInput.value); |
| if (isNaN(buyTime.getTime())) { |
| addLog('请选择有效的抢购时间', 'error'); |
| return; |
| } |
| |
| const now = new Date(); |
| if (buyTime <= now) { |
| addLog('抢购时间必须晚于当前时间', 'error'); |
| return; |
| } |
| |
| |
| isRunning = true; |
| testMode = false; |
| startBtn.disabled = true; |
| stopBtn.disabled = false; |
| testBtn.disabled = true; |
| currentStatus.className = 'status-badge status-ready'; |
| currentStatus.textContent = '等待抢购'; |
| |
| |
| addLog('抢购任务已启动', 'success'); |
| addLog(`抢购时间: ${formatDateTime(buyTime)}`, 'info'); |
| addLog(`商品链接: ${productUrlInput.value.trim()}`, 'info'); |
| addLog(`登录账号: ${userInfo.nickname}`, 'info'); |
| |
| |
| updateCountdown(buyTime); |
| countdownInterval = setInterval(() => updateCountdown(buyTime), 1000); |
| |
| |
| const timeDiff = buyTime - now; |
| const strategy = document.querySelector('input[name="strategy"]:checked').value; |
| |
| let executeTime = timeDiff; |
| if (strategy === 'early') { |
| executeTime = timeDiff - 1000; |
| } else if (strategy === 'random') { |
| executeTime = timeDiff - (500 + Math.random() * 1000); |
| } |
| |
| buyTimeout = setTimeout(() => { |
| executePurchase(); |
| }, executeTime); |
| } |
| |
| |
| function stopCountdown() { |
| if (countdownInterval) { |
| clearInterval(countdownInterval); |
| countdownInterval = null; |
| } |
| |
| if (buyTimeout) { |
| clearTimeout(buyTimeout); |
| buyTimeout = null; |
| } |
| |
| isRunning = false; |
| startBtn.disabled = false; |
| stopBtn.disabled = true; |
| testBtn.disabled = false; |
| currentStatus.className = 'status-badge status-waiting'; |
| currentStatus.textContent = '已停止'; |
| countdownDisplay.textContent = '--:--:--'; |
| progressBar.style.width = '0%'; |
| |
| addLog('抢购任务已停止', 'warning'); |
| } |
| |
| |
| function testModeToggle() { |
| if (isRunning) return; |
| |
| testMode = !testMode; |
| |
| if (testMode) { |
| testBtn.innerHTML = '<i class="fas fa-vial mr-2"></i>退出测试'; |
| testBtn.classList.remove('bg-blue-500', 'hover:bg-blue-600'); |
| testBtn.classList.add('bg-purple-500', 'hover:bg-purple-600'); |
| addLog('进入测试模式', 'info'); |
| |
| |
| const testTime = new Date(); |
| testTime.setSeconds(testTime.getSeconds() + 10); |
| buyTimeInput.value = formatDateTimeInput(testTime); |
| |
| |
| startCountdown(); |
| } |
| } |
| |
| |
| function updateCountdown(targetTime) { |
| const now = new Date(); |
| const diff = targetTime - now; |
| |
| if (diff <= 0) { |
| countdownDisplay.textContent = '00:00:00'; |
| progressBar.style.width = '100%'; |
| return; |
| } |
| |
| |
| const hours = Math.floor(diff / (1000 * 60 * 60)); |
| const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); |
| const seconds = Math.floor((diff % (1000 * 60)) / 1000); |
| |
| |
| countdownDisplay.textContent = |
| `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`; |
| |
| |
| const totalTime = targetTime - new Date(buyTimeInput.value); |
| const progress = ((totalTime - diff) / totalTime) * 100; |
| progressBar.style.width = `${Math.min(100, progress)}%`; |
| |
| |
| if (diff < 10000) { |
| countdownDisplay.classList.add('flashing'); |
| } else { |
| countdownDisplay.classList.remove('flashing'); |
| } |
| } |
| |
| |
| function executePurchase() { |
| |
| currentStatus.className = 'status-badge status-active'; |
| currentStatus.textContent = '抢购中...'; |
| countdownDisplay.textContent = '00:00:00'; |
| progressBar.style.width = '100%'; |
| |
| |
| addLog('开始执行抢购操作...', 'info'); |
| addLog(`使用账号: ${userInfo.nickname}`, 'info'); |
| |
| |
| setTimeout(() => { |
| addLog('正在加载商品页面...', 'info'); |
| |
| setTimeout(() => { |
| addLog('已加入购物车', 'success'); |
| |
| setTimeout(() => { |
| addLog('正在提交订单...', 'info'); |
| |
| setTimeout(() => { |
| |
| const isSuccess = Math.random() > 0.3 || testMode; |
| |
| if (isSuccess) { |
| addLog('抢购成功! 订单已生成', 'success'); |
| currentStatus.className = 'status-badge status-success'; |
| currentStatus.textContent = '抢购成功'; |
| } else { |
| addLog('抢购失败: 商品已售罄', 'error'); |
| currentStatus.className = 'status-badge status-error'; |
| currentStatus.textContent = '抢购失败'; |
| } |
| |
| |
| stopCountdown(); |
| }, 800); |
| }, 800); |
| }, 1000); |
| }, 500); |
| } |
| |
| |
| function addLog(message, type = 'info') { |
| |
| if (emptyLog.style.display !== 'none') { |
| emptyLog.style.display = 'none'; |
| } |
| |
| |
| const logEntry = document.createElement('div'); |
| logEntry.className = `log-entry log-${type}`; |
| |
| const time = new Date(); |
| logEntry.innerHTML = ` |
| <span class="log-time">${formatTime(time)}</span> |
| <span>${message}</span> |
| `; |
| |
| |
| logContainer.prepend(logEntry); |
| |
| |
| logEntries++; |
| logCount.textContent = logEntries; |
| |
| |
| logContainer.scrollTop = 0; |
| } |
| |
| |
| function clearLog() { |
| logContainer.innerHTML = ''; |
| emptyLog.style.display = 'block'; |
| logEntries = 0; |
| logCount.textContent = '0'; |
| addLog('日志已清空', 'info'); |
| } |
| |
| |
| function showLoginModal() { |
| loginModal.style.display = 'flex'; |
| generateQRCode(); |
| } |
| |
| |
| function hideLoginModal() { |
| loginModal.style.display = 'none'; |
| if (qrRefreshInterval) { |
| clearInterval(qrRefreshInterval); |
| qrRefreshInterval = null; |
| } |
| } |
| |
| |
| function generateQRCode() { |
| |
| if (qrRefreshInterval) { |
| clearInterval(qrRefreshInterval); |
| } |
| |
| |
| qrCodeElement.innerHTML = ` |
| <div class="flex flex-col items-center justify-center h-full"> |
| <div class="text-center"> |
| <div class="text-4xl mb-2">🔴</div> |
| <p class="text-sm text-gray-500">模拟二维码</p> |
| </div> |
| </div> |
| `; |
| |
| qrStatusElement.innerHTML = '<i class="fas fa-sync-alt fa-spin mr-2"></i>等待扫描...'; |
| |
| |
| let secondsLeft = 60; |
| qrRefreshInterval = setInterval(() => { |
| secondsLeft--; |
| |
| if (secondsLeft <= 0) { |
| qrStatusElement.innerHTML = '<i class="fas fa-exclamation-circle mr-2"></i>二维码已过期'; |
| clearInterval(qrRefreshInterval); |
| setTimeout(() => generateQRCode(), 1000); |
| } else { |
| qrStatusElement.innerHTML = `<i class="fas fa-sync-alt fa-spin mr-2"></i>二维码有效剩余 ${secondsLeft}秒`; |
| |
| |
| if (secondsLeft < 50 && Math.random() < 0.05) { |
| simulateLoginSuccess(); |
| } |
| } |
| }, 1000); |
| } |
| |
| |
| function simulateLoginSuccess() { |
| clearInterval(qrRefreshInterval); |
| |
| |
| userInfo = { |
| nickname: '京东用户_' + Math.floor(Math.random() * 10000), |
| avatar: 'https://img10.360buyimg.com/img/jfs/t1/143702/34/8864/4669/5f5f5719Ef3e8dff0/e2db058d5f7d6062.jpg' |
| }; |
| |
| isLoggedIn = true; |
| |
| |
| qrStatusElement.innerHTML = '<i class="fas fa-check-circle mr-2 text-green-500"></i>登录成功'; |
| setTimeout(hideLoginModal, 1000); |
| |
| |
| loginStatusElement.className = 'login-status logged'; |
| loginStatusElement.innerHTML = ` |
| <img src="${userInfo.avatar}" class="user-avatar"> |
| <span>已登录: ${userInfo.nickname}</span> |
| `; |
| |
| addLog('京东账号登录成功', 'success'); |
| addLog(`欢迎回来, ${userInfo.nickname}`, 'info'); |
| } |
| |
| |
| function formatTime(date) { |
| return `${padZero(date.getHours())}:${padZero(date.getMinutes())}:${padZero(date.getSeconds())}`; |
| } |
| |
| |
| function formatDateTime(date) { |
| return `${date.getFullYear()}-${padZero(date.getMonth() + 1)}-${padZero(date.getDate())} ${formatTime(date)}`; |
| } |
| |
| |
| function formatDateTimeInput(date) { |
| return `${date.getFullYear()}-${padZero(date.getMonth() + 1)}-${padZero(date.getDate())}T${padZero(date.getHours())}:${padZero(date.getMinutes())}`; |
| } |
| |
| |
| function padZero(num) { |
| return num < 10 ? `0${num}` : num; |
| } |
| |
| |
| updateProductDisplay(); |
| updateProductImage(); |
| }); |
| </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=Daddy-one/jingdong" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |