From 7b433aab9191cfb448ded30cac9e3b1f83fb8fde Mon Sep 17 00:00:00 2001 From: yinpeng <2291314224@qq.com> Date: Fri, 14 Feb 2025 00:21:28 +0800 Subject: [PATCH] =?UTF-8?q?refactor(static):=20=E5=B0=86=20CSS=20=E5=92=8C?= =?UTF-8?q?=20JS=20=E4=BB=A3=E7=A0=81=E5=88=86=E7=A6=BB=E5=88=B0=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E7=9A=84=E6=96=87=E4=BB=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 auth.html 中的 CSS 代码提取到 auth.css 文件中 - 将 auth.html 中的 JS 代码提取到 auth.js 文件中 - 更新 auth.html,引入外部的 CSS 和 JS 文件 - 新增 keys_status.css 和 keys_status.js 文件,用于 keys_status 页面 --- app/static/css/auth.css | 249 +++++++++++++++ app/static/css/keys_status.css | 423 ++++++++++++++++++++++++++ app/static/js/auth.js | 18 ++ app/static/js/keys_status.js | 135 +++++++++ app/templates/auth.html | 244 +-------------- app/templates/keys_status.html | 533 +-------------------------------- 6 files changed, 831 insertions(+), 771 deletions(-) create mode 100644 app/static/css/auth.css create mode 100644 app/static/css/keys_status.css create mode 100644 app/static/js/auth.js create mode 100644 app/static/js/keys_status.js diff --git a/app/static/css/auth.css b/app/static/css/auth.css new file mode 100644 index 0000000..12571ce --- /dev/null +++ b/app/static/css/auth.css @@ -0,0 +1,249 @@ +body { + font-family: 'Roboto', sans-serif; + line-height: 1.6; + margin: 0; + padding: 0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; +} + +.container { + max-width: 400px; + width: 90%; + background: rgba(255, 255, 255, 0.95); + padding: 40px; + border-radius: 20px; + box-shadow: 0 15px 35px rgba(0,0,0,0.2); + backdrop-filter: blur(10px); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.container:hover { + transform: translateY(-5px); + box-shadow: 0 20px 40px rgba(0,0,0,0.25); +} + +.logo { + text-align: center; + margin-bottom: 30px; + animation: fadeIn 1s ease; +} + +.logo i { + font-size: 48px; + color: #764ba2; + margin-bottom: 15px; +} + +h2 { + color: #2c3e50; + text-align: center; + margin-bottom: 30px; + font-weight: 700; + font-size: 24px; + animation: slideDown 0.5s ease; +} + +form { + display: flex; + flex-direction: column; + gap: 20px; +} + +.input-group { + position: relative; + animation: slideUp 0.5s ease; +} + +.input-group i { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + color: #764ba2; + font-size: 18px; +} + +input { + width: 100%; + padding: 12px 12px 12px 40px; + border: 2px solid #e0e0e0; + border-radius: 10px; + font-size: 16px; + box-sizing: border-box; + transition: all 0.3s ease; + background: rgba(255, 255, 255, 0.9); +} + +input:focus { + border-color: #764ba2; + box-shadow: 0 0 10px rgba(118, 75, 162, 0.2); + outline: none; +} + +button { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + padding: 14px; + border-radius: 10px; + cursor: pointer; + font-size: 16px; + font-weight: bold; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +button:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(118, 75, 162, 0.3); +} + +button:active { + transform: translateY(0); +} + +button::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + background: rgba(255, 255, 255, 0.2); + border-radius: 50%; + transform: translate(-50%, -50%); + transition: width 0.6s, height 0.6s; +} + +button:active::after { + width: 200px; + height: 200px; + opacity: 0; +} + +.error-message { + color: #e74c3c; + margin-top: 15px; + text-align: center; + font-weight: bold; + padding: 10px; + border-radius: 5px; + background: rgba(231, 76, 60, 0.1); + animation: shake 0.5s ease; +} + +.copyright { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + background: rgba(255, 255, 255, 0.9); + padding: 10px 0; + text-align: center; + font-size: 14px; + color: #2c3e50; + backdrop-filter: blur(5px); + border-top: 1px solid rgba(0,0,0,0.1); +} + +.copyright a { + color: #764ba2; + text-decoration: none; + transition: color 0.3s ease; +} + +.copyright a:hover { + color: #667eea; +} + +.copyright img { + width: 20px; + height: 20px; + border-radius: 50%; + vertical-align: middle; + margin-right: 5px; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideDown { + from { transform: translateY(-20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } +} + +@keyframes slideUp { + from { transform: translateY(20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } +} + +@keyframes shake { + 0%, 100% { transform: translateX(0); } + 25% { transform: translateX(-5px); } + 75% { transform: translateX(5px); } +} + +@media (max-width: 768px) { + .container { + width: 85%; + padding: 30px; + } + .logo i { + font-size: 40px; + } + h2 { + font-size: 22px; + } + input { + padding: 10px 10px 10px 35px; + font-size: 15px; + } + .input-group i { + font-size: 16px; + } + button { + padding: 12px; + font-size: 15px; + } +} + +@media (max-width: 480px) { + .container { + width: 90%; + padding: 25px; + } + .logo i { + font-size: 36px; + } + h2 { + font-size: 20px; + margin-bottom: 25px; + } + form { + gap: 15px; + } + input { + padding: 10px 10px 10px 32px; + font-size: 14px; + } + .input-group i { + font-size: 15px; + left: 10px; + } + button { + padding: 10px; + font-size: 14px; + } + .error-message { + font-size: 14px; + padding: 8px; + margin-top: 12px; + } +} diff --git a/app/static/css/keys_status.css b/app/static/css/keys_status.css new file mode 100644 index 0000000..093b56d --- /dev/null +++ b/app/static/css/keys_status.css @@ -0,0 +1,423 @@ +body { + font-family: 'Roboto', sans-serif; + line-height: 1.6; + margin: 0; + padding: 20px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; +} + +.container { + max-width: 900px; + width: 95%; + background: rgba(255, 255, 255, 0.95); + padding: 40px; + border-radius: 20px; + box-shadow: 0 15px 35px rgba(0,0,0,0.2); + backdrop-filter: blur(10px); + position: relative; + margin: 20px auto; + overflow-y: auto; + max-height: calc(100vh - 40px); + scrollbar-width: none; + -ms-overflow-style: none; +} + +.container::-webkit-scrollbar { + display: none; +} + +h1 { + color: #2c3e50; + text-align: center; + margin-bottom: 30px; + font-weight: 700; + font-size: 32px; + position: relative; + padding-bottom: 15px; +} + +h1::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 100px; + height: 4px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 2px; +} + +.key-list { + margin-bottom: 30px; + background: rgba(248, 249, 250, 0.9); + padding: 25px; + border-radius: 15px; + transition: all 0.3s ease; + border: 1px solid rgba(0,0,0,0.1); + animation: fadeIn 0.5s ease forwards; +} + +.key-list:hover { + transform: translateY(-5px); + box-shadow: 0 10px 20px rgba(0,0,0,0.1); +} + +.key-list:nth-child(2) { + animation-delay: 0.2s; +} + +.key-list h2 { + color: #2c3e50; + margin-bottom: 20px; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 1.5em; + padding-bottom: 10px; + border-bottom: 2px solid rgba(0,0,0,0.1); + cursor: pointer; +} + +.key-list h2 .toggle-icon { + margin-right: 10px; + transition: transform 0.3s ease; +} + +.key-list h2 .toggle-icon.collapsed { + transform: rotate(-90deg); +} + +.key-list .key-content { + transition: all 0.3s ease-out; + overflow: hidden; + height: auto; + opacity: 1; +} + +.key-list .key-content.collapsed { + height: 0; + opacity: 0; + padding-top: 0; + padding-bottom: 0; +} + +ul { + list-style-type: none; + padding: 0; + margin: 0; +} + +li { + background: white; + border: 1px solid rgba(0,0,0,0.1); + margin-bottom: 12px; + padding: 15px; + border-radius: 10px; + transition: all 0.3s ease; + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: 0 2px 5px rgba(0,0,0,0.05); +} + +li:hover { + transform: translateX(5px); + box-shadow: 0 5px 15px rgba(0,0,0,0.1); +} + +.key-info { + display: flex; + align-items: center; + gap: 15px; + flex: 1; +} + +.key-text { + font-family: 'Roboto Mono', monospace; + color: #2c3e50; +} + +.fail-count { + background: rgba(231, 76, 60, 0.1); + color: #e74c3c; + padding: 4px 10px; + border-radius: 15px; + font-size: 0.85em; + display: flex; + align-items: center; + gap: 5px; +} + +.fail-count i { + font-size: 12px; +} + +.copy-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + padding: 8px 15px; + border-radius: 8px; + cursor: pointer; + font-size: 14px; + font-weight: bold; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 5px; +} + +.copy-btn:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(118, 75, 162, 0.3); +} + +.copy-btn:active { + transform: translateY(0); +} + +.copy-btn i { + font-size: 14px; +} + +.total { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 15px 25px; + border-radius: 10px; + font-weight: bold; + text-align: center; + font-size: 1.2em; + margin-top: 30px; + box-shadow: 0 5px 15px rgba(0,0,0,0.1); +} + +#copyStatus { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: rgba(39, 174, 96, 0.95); + color: white; + padding: 15px 30px; + border-radius: 25px; + font-weight: bold; + opacity: 0; + transition: all 0.3s ease; + backdrop-filter: blur(5px); + box-shadow: 0 5px 15px rgba(0,0,0,0.2); + z-index: 1000; + text-align: center; + min-width: 200px; +} + +.status-badge { + padding: 4px 12px; + border-radius: 15px; + font-size: 0.9em; + font-weight: bold; + margin-right: 10px; +} + +.status-valid { + background: rgba(39, 174, 96, 0.1); + color: #27ae60; +} + +.status-invalid { + background: rgba(231, 76, 60, 0.1); + color: #e74c3c; +} + +.scroll-buttons { + position: fixed; + right: 20px; + bottom: 20px; + display: none; + flex-direction: column; + gap: 10px; + z-index: 1000; +} + +.scroll-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + width: 40px; + height: 40px; + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + transition: all 0.3s ease; + backdrop-filter: blur(5px); + box-shadow: 0 2px 10px rgba(0,0,0,0.2); +} + +.scroll-btn:hover { + background: linear-gradient(135deg, #764ba2 0%, #667eea 100%); + transform: scale(1.1); +} + +.scroll-btn:active { + transform: scale(0.95); +} + +.refresh-btn { + position: fixed; + top: 20px; + right: 20px; + z-index: 1000; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 25px; + cursor: pointer; + font-size: 14px; + font-weight: bold; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); +} + +.refresh-btn:hover { + transform: scale(1.05); + box-shadow: 0 8px 20px rgba(118, 75, 162, 0.3); + background: linear-gradient(135deg, #764ba2 0%, #667eea 100%); +} + +.refresh-btn:active { + transform: scale(0.95); +} + +.refresh-btn i { + transition: transform 0.5s ease; +} + +.refresh-btn.loading i { + animation: spin 1s linear infinite; +} + +.copyright { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + background: rgba(255, 255, 255, 0.9); + padding: 10px 0; + text-align: center; + font-size: 14px; + color: #2c3e50; + backdrop-filter: blur(5px); + border-top: 1px solid rgba(0,0,0,0.1); +} + +.copyright a { + color: #764ba2; + text-decoration: none; + transition: color 0.3s ease; +} + +.copyright a:hover { + color: #667eea; +} + +.copyright img { + width: 20px; + height: 20px; + border-radius: 50%; + vertical-align: middle; + margin-right: 5px; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +@media (max-width: 768px) { + .container { + width: 100%; + padding: 20px; + margin: 10px auto; + } + body { + padding: 10px; + } + h1 { + font-size: 24px; + } + .key-list h2 { + font-size: 1.2em; + flex-direction: column; + gap: 10px; + align-items: flex-start; + } + .key-info { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + li { + flex-direction: column; + gap: 10px; + } + .copy-btn { + width: 100%; + justify-content: center; + } + .key-text { + word-break: break-all; + } + .scroll-buttons { + right: 10px; + bottom: 10px; + } + .scroll-btn { + width: 35px; + height: 35px; + font-size: 16px; + } + .refresh-btn { + top: 10px; + right: 10px; + padding: 8px 16px; + font-size: 12px; + } +} + +@media (max-width: 480px) { + .container { + padding: 15px; + } + h1 { + font-size: 20px; + } + .key-list { + padding: 15px; + } + .status-badge { + padding: 3px 8px; + font-size: 0.8em; + } + .fail-count { + font-size: 0.8em; + } + .total { + font-size: 1em; + padding: 12px 20px; + } +} diff --git a/app/static/js/auth.js b/app/static/js/auth.js new file mode 100644 index 0000000..bad01ab --- /dev/null +++ b/app/static/js/auth.js @@ -0,0 +1,18 @@ +if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('/static/service-worker.js') + .then(registration => { + console.log('ServiceWorker注册成功:', registration.scope); + }) + .catch(error => { + console.log('ServiceWorker注册失败:', error); + }); + }); +} + +document.addEventListener('DOMContentLoaded', () => { + const copyrightYear = document.querySelector('.copyright script'); + if (copyrightYear) { + copyrightYear.textContent = new Date().getFullYear(); + } +}); diff --git a/app/static/js/keys_status.js b/app/static/js/keys_status.js new file mode 100644 index 0000000..1ab80e9 --- /dev/null +++ b/app/static/js/keys_status.js @@ -0,0 +1,135 @@ +function copyToClipboard(text) { + if (navigator.clipboard && navigator.clipboard.writeText) { + return navigator.clipboard.writeText(text); + } else { + return new Promise((resolve, reject) => { + const textArea = document.createElement("textarea"); + textArea.value = text; + textArea.style.position = "fixed"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + const successful = document.execCommand('copy'); + document.body.removeChild(textArea); + if (successful) { + resolve(); + } else { + reject(new Error('复制失败')); + } + } catch (err) { + document.body.removeChild(textArea); + reject(err); + } + }); + } +} + +function copyKeys(type) { + const keys = Array.from(document.querySelectorAll(`#${type}Keys .key-text`)).map(span => span.textContent.trim()); + const jsonKeys = JSON.stringify(keys); + + copyToClipboard(jsonKeys) + .then(() => { + showCopyStatus(`已成功复制${type === 'valid' ? '有效' : '无效'}密钥到剪贴板`); + }) + .catch((err) => { + console.error('无法复制文本: ', err); + showCopyStatus('复制失败,请重试'); + }); +} + +function copyKey(key) { + copyToClipboard(key) + .then(() => { + showCopyStatus(`已成功复制密钥到剪贴板`); + }) + .catch((err) => { + console.error('无法复制文本: ', err); + showCopyStatus('复制失败,请重试'); + }); +} + +function showCopyStatus(message) { + const statusElement = document.getElementById('copyStatus'); + statusElement.textContent = message; + statusElement.style.opacity = 1; + setTimeout(() => { + statusElement.style.opacity = 0; + }, 2000); +} + +function scrollToTop() { + const container = document.querySelector('.container'); + container.scrollTo({ + top: 0, + behavior: 'smooth' + }); +} + +function scrollToBottom() { + const container = document.querySelector('.container'); + container.scrollTo({ + top: container.scrollHeight, + behavior: 'smooth' + }); +} + +function updateScrollButtons() { + const container = document.querySelector('.container'); + const scrollButtons = document.querySelector('.scroll-buttons'); + if (container.scrollHeight > container.clientHeight) { + scrollButtons.style.display = 'flex'; + } else { + scrollButtons.style.display = 'none'; + } +} + +function refreshPage(button) { + button.classList.add('loading'); + button.disabled = true; + + setTimeout(() => { + window.location.reload(); + }, 300); +} + +function toggleSection(header, sectionId) { + const toggleIcon = header.querySelector('.toggle-icon'); + const content = header.nextElementSibling; + + toggleIcon.classList.toggle('collapsed'); + content.classList.toggle('collapsed'); +} + +// 初始化 +document.addEventListener('DOMContentLoaded', () => { + // 检查滚动按钮 + updateScrollButtons(); + + // 监听展开/折叠事件 + document.querySelectorAll('.key-list h2').forEach(header => { + header.addEventListener('click', () => { + setTimeout(updateScrollButtons, 300); + }); + }); + + // 更新版权年份 + const copyrightYear = document.querySelector('.copyright script'); + if (copyrightYear) { + copyrightYear.textContent = new Date().getFullYear(); + } +}); + +// Service Worker registration +if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('/static/service-worker.js') + .then(registration => { + console.log('ServiceWorker注册成功:', registration.scope); + }) + .catch(error => { + console.log('ServiceWorker注册失败:', error); + }); + }); +} diff --git a/app/templates/auth.html b/app/templates/auth.html index 9e7e086..0945654 100644 --- a/app/templates/auth.html +++ b/app/templates/auth.html @@ -12,205 +12,7 @@ - +
@@ -231,52 +33,10 @@

{{ error }}

{% endif %}
- - + diff --git a/app/templates/keys_status.html b/app/templates/keys_status.html index ff86703..da69302 100644 --- a/app/templates/keys_status.html +++ b/app/templates/keys_status.html @@ -12,380 +12,12 @@ - +

API密钥状态

@@ -474,168 +106,11 @@
- - - + +