diff --git a/index.html b/index.html index ff08653..c70d4da 100644 --- a/index.html +++ b/index.html @@ -617,6 +617,65 @@ :root[data-theme="light"] .theme-toggle .sun-icon { display: block; } :root[data-theme="light"] .theme-toggle .moon-icon { display: none; } + /* ===== 访问计数实时动画 ===== */ + .visitor-num { + display: inline-block; + transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), color 0.4s ease; + } + .visitor-num.bump { + transform: scale(1.6) rotate(-5deg); + color: var(--gradient-2); + text-shadow: 0 0 20px color-mix(in oklch, var(--gradient-2) 60%, transparent); + } + @keyframes pulseGlow { + 0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--gradient-2) 40%, transparent); } + 100% { box-shadow: 0 0 0 12px transparent; } + } + .visitor-pulse { + animation: pulseGlow 0.8s ease-out; + } + .visitor-toast { + position: fixed; + bottom: 2rem; + left: 50%; + transform: translateX(-50%) translateY(120%); + z-index: 90; + padding: 0.6rem 1.2rem; + border-radius: 1rem; + font-size: 0.75rem; + font-weight: 600; + color: var(--text-primary); + background: var(--glass-bg); + border: 1px solid var(--glass-border); + backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate)); + -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate)); + box-shadow: 0 12px 40px var(--glass-shadow), inset 0 1px 0 var(--glass-inset); + opacity: 0; + transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.4s ease; + pointer-events: none; + white-space: nowrap; + } + .visitor-toast.show { + transform: translateX(-50%) translateY(0); + opacity: 1; + } + .visitor-toast .toast-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.25rem; + height: 1.25rem; + border-radius: 50%; + background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2)); + color: white; + margin-right: 0.5rem; + vertical-align: middle; + } + .visitor-toast .toast-icon svg { + width: 0.75rem; + height: 0.75rem; + } + /* ===== 浅色模式文字适配 ===== */ :root[data-theme="light"] .text-slate-100 { color: oklch(0.2 0.01 260) !important; } :root[data-theme="light"] .text-slate-400 { color: oklch(0.45 0.02 260) !important; } @@ -701,11 +760,19 @@

© 2026 AI 应用门户 · AI Application Portal

- 本站已被访问 -- + 本站已被访问 --

+ +
+ + + + 有新访客到来! +
+
@@ -1173,27 +1240,78 @@ /** * 调用第三方计数 API 获取并递增全局访问量,更新页脚显示。 + * 之后定时轮询 get 接口(不递增),检测新访客并艺术化提示。 */ + let _lastCount = null; + let _toastTimer = null; + function updateVisitorCount() { const countKey = 'all8ai-portal-visits-2026'; - const url = `https://countapi.mileshilliard.com/api/v1/hit/${countKey}`; - fetch(url) + const hitUrl = `https://countapi.mileshilliard.com/api/v1/hit/${countKey}`; + fetch(hitUrl) .then(res => res.json()) .then(data => { if (data && data.value !== undefined) { const count = Number(data.value); + _lastCount = count; const numEl = document.getElementById('visitorCountNum'); - const numEnEl = document.getElementById('visitorCountNumEn'); - const wrapEl = document.getElementById('visitorCount'); if (numEl) numEl.textContent = count.toLocaleString(); - if (numEnEl) numEnEl.textContent = count.toLocaleString(); + const wrapEl = document.getElementById('visitorCount'); if (wrapEl) wrapEl.style.opacity = '1'; } }) .catch(() => {}); } + function pollVisitorCount() { + const countKey = 'all8ai-portal-visits-2026'; + const getUrl = `https://countapi.mileshilliard.com/api/v1/get/${countKey}`; + fetch(getUrl) + .then(res => res.json()) + .then(data => { + if (data && data.value !== undefined) { + const count = Number(data.value); + if (_lastCount !== null && count > _lastCount) { + const diff = count - _lastCount; + _lastCount = count; + animateVisitorCount(count, diff); + } else if (_lastCount !== null && count < _lastCount) { + _lastCount = count; + } + } + }) + .catch(() => {}); + } + + function animateVisitorCount(count, diff) { + const numEl = document.getElementById('visitorCountNum'); + const wrapEl = document.getElementById('visitorCount'); + if (!numEl) return; + + numEl.classList.add('bump'); + if (wrapEl) wrapEl.classList.add('visitor-pulse'); + setTimeout(() => { + numEl.textContent = count.toLocaleString(); + }, 200); + setTimeout(() => { + numEl.classList.remove('bump'); + if (wrapEl) wrapEl.classList.remove('visitor-pulse'); + }, 800); + + const toast = document.getElementById('visitorToast'); + const toastText = document.getElementById('visitorToastText'); + if (toast && toastText) { + toastText.textContent = `✨ 新访客 +${diff} · 当前 ${count.toLocaleString()} 次`; + toast.classList.add('show'); + if (_toastTimer) clearTimeout(_toastTimer); + _toastTimer = setTimeout(() => { + toast.classList.remove('show'); + }, 4000); + } + } + updateVisitorCount(); + setInterval(pollVisitorCount, 10000); /** * 帮助弹窗的测试账号数据,中英双语展示。