Files

61 lines
2.2 KiB
JavaScript

/* ================= 歌单每日随机排序 ================= */
/* 顺序只由「日期」决定:同一天所有访客看到的顺序完全一致,
北京时间每天 0 点自动换一套(无需重新构建,静态页面也能生效)。 */
(function () {
const list = document.querySelector('.song-list');
if (!list) return;
const items = Array.from(list.children).filter((el) =>
el.classList && el.classList.contains('song')
);
if (items.length < 2) return;
// 北京时间(UTC+8)当天,如 2026-10-06
const day = new Date(Date.now() + 8 * 60 * 60 * 1000)
.toISOString()
.slice(0, 10);
// FNV-1a:把日期压成 32 位种子
let seed = 0x811c9dc5;
for (let i = 0; i < day.length; i++) {
seed ^= day.charCodeAt(i);
seed = Math.imul(seed, 0x01000193) >>> 0;
}
// mulberry32:同一种子 → 同一串伪随机数(跨浏览器一致)
function rand() {
seed = (seed + 0x6d2b79f5) >>> 0;
let t = seed;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
}
// Fisher–Yates 洗牌(固定种子,结果可复现)
for (let i = items.length - 1; i > 0; i--) {
const j = Math.floor(rand() * (i + 1));
const tmp = items[i];
items[i] = items[j];
items[j] = tmp;
}
// 按新顺序放回,并重排序号。
// 注意:这里不要写 transition-delay。入场错峰统一由 pages.js 在元素
// 进入视口时按「当前文档顺序」计算;两处各写一套延时就会互相错开。
const frag = document.createDocumentFragment();
items.forEach((el, i) => {
const no = el.querySelector('.no');
if (no) no.textContent = String(i + 1).padStart(2, '0');
frag.appendChild(el);
});
list.appendChild(frag);
// 提示条上标注当前生效的日期
const tip = document.getElementById('shuffle-tip');
const dayEl = document.getElementById('shuffle-day');
if (tip && dayEl) {
dayEl.textContent = day;
tip.hidden = false;
}
})();