function randomPost(trigger) { const source = trigger instanceof Element ? trigger : document.activeElement?.closest?.('.nav-random, [onclick*="randomPost"]'); const overlay = document.createElement('div'); const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches; overlay.className = 'random-post-transition'; overlay.setAttribute('role', 'status'); overlay.setAttribute('aria-live', 'polite'); overlay.innerHTML = `
\u6b63\u5728\u62bd\u53d6\u4e00\u7bc7\u6587\u7ae0
`; source?.classList.add('is-randomizing'); source?.setAttribute('aria-busy', 'true'); document.body.appendChild(overlay); requestAnimationFrame(() => overlay.classList.add('is-visible')); const finish = href => { const delay = reduceMotion ? 80 : 1250; window.setTimeout(() => { location.href = href; }, delay); }; const startCardFlight = posts => { if (reduceMotion) return; const flight = overlay.querySelector('.random-post-flight'); if (!flight) return; const candidates = posts .filter(post => post && typeof post.href === 'string' && post.href.startsWith('/posts/')) .map(post => ({ title: typeof post.title === 'string' && post.title.trim() ? post.title.trim() : '\u672a\u547d\u540d\u6587\u7ae0', meta: typeof post.category === 'string' && post.category.trim() ? post.category.trim() : '\u968f\u673a\u6587\u7ae0', })); const pool = candidates.length ? candidates : [{ title: '\u968f\u673a\u6587\u7ae0', meta: '\u6b63\u5728\u62bd\u53d6' }]; const count = Math.min(9, Math.max(5, pool.length)); for (let index = 0; index < count; index += 1) { const post = pool[Math.floor(Math.random() * pool.length)]; const card = document.createElement('div'); card.className = 'random-post-flying-card'; card.style.setProperty('--flight-delay', `${index * 0.11}s`); card.style.setProperty('--flight-y', `${-42 + Math.random() * 84}px`); card.style.setProperty('--flight-rotate', `${-8 + Math.random() * 16}deg`); const meta = document.createElement('small'); const title = document.createElement('strong'); meta.textContent = post.meta; title.textContent = post.title; card.append(meta, title); flight.appendChild(card); } }; const reset = () => { source?.classList.remove('is-randomizing'); source?.removeAttribute('aria-busy'); overlay.classList.remove('is-visible'); window.setTimeout(() => overlay.remove(), reduceMotion ? 0 : 180); }; fetch('/api/posts.json') .then(res => { if (!res.ok) throw new Error(`Failed to load posts: ${res.status}`); return res.json(); }) .then(posts => { const postLinks = posts .map(post => post && post.href) .filter(href => typeof href === 'string' && href.startsWith('/posts/')); if (postLinks.length === 0) { console.warn('No posts available for random navigation.'); reset(); return; } startCardFlight(posts); finish(postLinks[Math.floor(Math.random() * postLinks.length)]); }) .catch(error => { console.error('Random post navigation failed:', error); reset(); }); }