(function () { var header = document.querySelector(".site-header"); var drawer = document.querySelector("[data-drawer]"); var openBtn = document.querySelector("[data-drawer-open]"); var userMenu = document.querySelector("[data-user-menu]"); if (header) { var threshold = 48; var ticking = false; function measure() { document.documentElement.style.setProperty("--site-header-height", header.getBoundingClientRect().height + "px"); } function update() { ticking = false; header.classList.toggle("is-scrolled", window.scrollY > threshold); } function onScroll() { if (ticking) return; ticking = true; window.requestAnimationFrame(update); } measure(); update(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", measure); if ("ResizeObserver" in window) new ResizeObserver(measure).observe(header); } // 用户下拉菜单 if (userMenu) { var toggle = userMenu.querySelector("[data-user-menu-toggle]"); function openUserMenu() { userMenu.classList.add("is-open"); if (toggle) toggle.setAttribute("aria-expanded", "true"); } function closeUserMenu() { userMenu.classList.remove("is-open"); if (toggle) toggle.setAttribute("aria-expanded", "false"); } function toggleUserMenu(e) { e.stopPropagation(); if (userMenu.classList.contains("is-open")) { closeUserMenu(); } else { openUserMenu(); } } if (toggle) { toggle.addEventListener("click", toggleUserMenu); } document.addEventListener("click", function (e) { if (!userMenu.contains(e.target)) { closeUserMenu(); } }); document.addEventListener("keydown", function (e) { if (e.key === "Escape") closeUserMenu(); }); } // 左侧抽屉 if (drawer && openBtn) { var closeEls = drawer.querySelectorAll("[data-drawer-close]"); function openDrawer() { drawer.classList.add("is-open"); document.body.classList.add("drawer-open"); openBtn.setAttribute("aria-expanded", "true"); } function closeDrawer() { drawer.classList.remove("is-open"); document.body.classList.remove("drawer-open"); openBtn.setAttribute("aria-expanded", "false"); } openBtn.setAttribute("aria-expanded", "false"); openBtn.setAttribute("aria-controls", "site-drawer"); openBtn.addEventListener("click", openDrawer); closeEls.forEach(function (el) { el.addEventListener("click", closeDrawer); }); document.addEventListener("keydown", function (e) { if (e.key === "Escape" && drawer.classList.contains("is-open")) { closeDrawer(); } }); } function openAccountSwitch(event) { if (event) event.preventDefault(); if (userMenu) { userMenu.classList.remove("is-open"); var userToggle = userMenu.querySelector("[data-user-menu-toggle]"); if (userToggle) userToggle.setAttribute("aria-expanded", "false"); } if (drawer) { drawer.classList.remove("is-open"); document.body.classList.remove("drawer-open"); if (openBtn) openBtn.setAttribute("aria-expanded", "false"); } if (typeof window.openAccountSwitchLogin === "function") { window.openAccountSwitchLogin(); return; } if (typeof window.openLoginPop === "function") { window.openLoginPop(); return; } window.location.href = "/login"; } document.querySelectorAll("[data-account-switch]").forEach(function (btn) { btn.addEventListener("click", openAccountSwitch); }); // 搜索表单:走路径 /search/{q},不用 query;同时写入本地搜索历史 var SEARCH_HISTORY_KEY = "hgdj_search_history"; var SEARCH_HISTORY_MAX = 10; function searchResultsPath(q) { q = String(q || "").trim(); if (!q) return "/search"; return "/search/" + encodeURIComponent(q).replace(/%20/g, "%20"); } function readSearchHistory() { try { var raw = window.localStorage.getItem(SEARCH_HISTORY_KEY); var list = raw ? JSON.parse(raw) : []; if (!Array.isArray(list)) return []; return list .map(function (item) { return String(item || "").trim(); }) .filter(Boolean) .slice(0, SEARCH_HISTORY_MAX); } catch (_) { return []; } } function writeSearchHistory(list) { try { window.localStorage.setItem( SEARCH_HISTORY_KEY, JSON.stringify(list.slice(0, SEARCH_HISTORY_MAX)) ); } catch (_) { /* ignore quota / private mode */ } } function pushSearchHistory(q) { q = String(q || "").trim(); if (!q) return; var list = readSearchHistory().filter(function (item) { return item !== q; }); list.unshift(q); writeSearchHistory(list); } function clearSearchHistory() { try { window.localStorage.removeItem(SEARCH_HISTORY_KEY); } catch (_) { /* ignore */ } } document.querySelectorAll("form[data-path-search]").forEach(function (form) { form.addEventListener("submit", function (event) { event.preventDefault(); var input = form.querySelector('input[type="search"], input[name="q"]'); var q = input ? String(input.value || "").trim() : ""; if (!q) { if (input) input.focus(); return; } pushSearchHistory(q); window.location.href = searchResultsPath(q); }); var input = form.querySelector("[data-header-search-input], input[type='search'], input[name='q']"); var clear = form.querySelector("[data-header-search-clear]"); if (input && clear) { function syncClear() { clear.hidden = !String(input.value || "").trim(); } input.addEventListener("input", syncClear); clear.addEventListener("click", function () { input.value = ""; syncClear(); input.dispatchEvent(new Event("input", { bubbles: true })); input.focus(); }); syncClear(); } // PC header 搜索下拉:聚焦展开历史 + 热搜;输入时切换联想 var dropdown = form.querySelector("[data-header-search-dropdown]"); if (!dropdown || !input) return; var historyBox = form.querySelector("[data-header-search-history]"); var historyChips = form.querySelector("[data-header-history-chips]"); var historyClear = form.querySelector("[data-header-history-clear]"); var idleBox = form.querySelector("[data-header-search-idle]"); var suggestBox = form.querySelector("[data-header-search-suggest]"); var closeTimer = null; var suggestTimer = null; var suggestSeq = 0; var PLACEHOLDER_IMG = "/static/images/placeholder.png?v=2"; function escapeHtml(text) { return String(text || "") .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function highlightHTML(text, keyword) { var raw = String(text || ""); var key = String(keyword || "").trim(); if (!raw) return ""; if (!key) return escapeHtml(raw); var lowerRaw = raw.toLowerCase(); var lowerKey = key.toLowerCase(); var idx = lowerRaw.indexOf(lowerKey); if (idx < 0) return escapeHtml(raw); var before = raw.slice(0, idx); var hit = raw.slice(idx, idx + key.length); var after = raw.slice(idx + key.length); return ( escapeHtml(before) + '' + escapeHtml(hit) + "" + escapeHtml(after) ); } function renderHistory() { if (!historyBox || !historyChips) return; var list = readSearchHistory(); historyChips.innerHTML = ""; if (!list.length) { historyBox.hidden = true; return; } historyBox.hidden = false; list.forEach(function (term) { var link = document.createElement("a"); link.className = "search-dropdown__chip"; link.href = searchResultsPath(term); link.textContent = term; historyChips.appendChild(link); }); } function showIdlePanel() { if (idleBox) idleBox.hidden = false; if (suggestBox) { suggestBox.hidden = true; suggestBox.innerHTML = ""; } } function showSuggestPanel() { if (idleBox) idleBox.hidden = true; if (suggestBox) suggestBox.hidden = false; } function renderSuggest(data, keyword) { if (!suggestBox) return; var html = ""; var feature = data && data.feature; var items = (data && data.items) || []; if (feature && feature.url) { html += '
' + '' + '' +
          escapeHtml(feature.title || ' + "" + '
' + '

' + highlightHTML(feature.title, keyword) + "

" + (feature.meta ? '

' + escapeHtml(feature.meta) + "

" : "") + "
" + '' + '播放播放' + "
"; } if (items.length) { html += '
'; items.forEach(function (item) { if (!item || !item.url) return; html += '' + '' + '' + highlightHTML(item.title || item.query || "", keyword) + "" + '' + escapeHtml(item.kind || "") + "" + ""; }); html += "
"; } else if (!feature) { html += '

暂无相关结果,回车搜索“' + escapeHtml(keyword) + '”

'; } suggestBox.innerHTML = html; showSuggestPanel(); if (typeof window.initLazyImages === "function") { window.initLazyImages(suggestBox, { eager: true }); } } function fetchSuggest(keyword) { var q = String(keyword || "").trim(); if (!q || !suggestBox) { showIdlePanel(); openDropdown(); return; } var seq = ++suggestSeq; showSuggestPanel(); suggestBox.innerHTML = '

搜索中…

'; openDropdown(); var req; if (window.HttpRequest && typeof window.HttpRequest.get === "function") { req = window.HttpRequest.get("/api/web/search/suggest", { params: { keyword: q }, }); } else { req = fetch( "/api/web/search/suggest?keyword=" + encodeURIComponent(q), { credentials: "include", headers: { Accept: "application/json" } } ).then(function (res) { return res.json(); }); } Promise.resolve(req) .then(function (data) { if (seq !== suggestSeq) return; renderSuggest(data || {}, q); }) .catch(function () { if (seq !== suggestSeq) return; renderSuggest( { feature: null, items: [ { title: q, kind: "搜索", query: q, url: searchResultsPath(q), }, ], }, q ); }); } function scheduleSuggest() { var q = String(input.value || "").trim(); if (suggestTimer) clearTimeout(suggestTimer); if (!q) { suggestSeq += 1; showIdlePanel(); openDropdown(); return; } suggestTimer = setTimeout(function () { suggestTimer = null; fetchSuggest(q); }, 220); } function openDropdown() { if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } var q = String(input.value || "").trim(); if (q) { if (suggestBox && suggestBox.hidden) { scheduleSuggest(); } dropdown.hidden = false; form.classList.add("is-open"); input.setAttribute("aria-expanded", "true"); return; } showIdlePanel(); renderHistory(); var hasHistory = historyBox && !historyBox.hidden; var hasHot = !!(idleBox && idleBox.querySelector(".search-dropdown__hot")); if (!hasHistory && !hasHot) { dropdown.hidden = true; form.classList.remove("is-open"); input.setAttribute("aria-expanded", "false"); return; } dropdown.hidden = false; form.classList.add("is-open"); input.setAttribute("aria-expanded", "true"); } function closeDropdown() { dropdown.hidden = true; form.classList.remove("is-open"); input.setAttribute("aria-expanded", "false"); } function scheduleClose() { if (closeTimer) clearTimeout(closeTimer); closeTimer = setTimeout(function () { closeTimer = null; if (!form.contains(document.activeElement)) { closeDropdown(); } }, 120); } input.addEventListener("focus", openDropdown); input.addEventListener("click", openDropdown); input.addEventListener("input", function () { if (clear) clear.hidden = !String(input.value || "").trim(); scheduleSuggest(); }); input.addEventListener("blur", scheduleClose); dropdown.addEventListener("mousedown", function (event) { // 点击下拉内链接/按钮时先阻止 input blur 抢先关闭 event.preventDefault(); }); dropdown.addEventListener("click", function (event) { var chip = event.target.closest ? event.target.closest( ".search-dropdown__chip, .search-dropdown__link, .search-dropdown__feature-play, .search-dropdown__feature-cover, .search-dropdown__suggest-item" ) : null; if (chip && chip.href) { var q = ""; if (chip.classList.contains("search-dropdown__chip")) { q = String(chip.textContent || "").trim(); } else if (chip.classList.contains("search-dropdown__link")) { var name = chip.querySelector(".search-dropdown__name"); if (name) q = String(name.textContent || "").trim(); } else if (chip.getAttribute("data-suggest-query")) { q = String(chip.getAttribute("data-suggest-query") || "").trim(); } else { q = String(input.value || "").trim(); } if (q) pushSearchHistory(q); window.location.href = chip.href; } }); if (historyClear) { historyClear.addEventListener("click", function (event) { event.preventDefault(); event.stopPropagation(); clearSearchHistory(); renderHistory(); openDropdown(); input.focus(); }); } document.addEventListener("keydown", function (event) { if (event.key === "Escape" && !dropdown.hidden) { closeDropdown(); input.blur(); } }); document.addEventListener("mousedown", function (event) { if (dropdown.hidden) return; if (form.contains(event.target)) return; closeDropdown(); }); }); var PLACEHOLDER = "/static/images/placeholder.png?v=2"; var DEFAULT_AVATAR = "/static/images/profile/avatar.png"; function usableAvatar(url) { var u = String(url || "").trim(); if (!u) return ""; if (/^https?:\/\//i.test(u) || u.indexOf("/static/") === 0) return u; return ""; } function setAvatarImg(img, url) { if (!img) return; var src = usableAvatar(url); img.removeAttribute("data-decrypted"); img.removeAttribute("data-decrypt-failed"); if (src && typeof window.shouldDecryptImage === "function" && window.shouldDecryptImage(src)) { img.classList.add("lazy"); img.src = PLACEHOLDER; img.setAttribute("data-src", src); img.setAttribute("data-lazy-eager", "1"); } else { img.classList.remove("lazy"); img.removeAttribute("data-src"); img.removeAttribute("data-lazy-eager"); img.src = src || DEFAULT_AVATAR; } } function refreshAvatarDecrypt(root) { var scope = root || document; if (typeof window.initLazyImages === "function") { window.initLazyImages(scope, { eager: true }); return; } if (typeof window.loadLazyNode !== "function") return; scope .querySelectorAll( "img.user-chip__avatar.lazy[data-src], img.user-menu__avatar.lazy[data-src], img.drawer__avatar.lazy[data-src], img.play-composer__avatar-img.lazy[data-src]" ) .forEach(function (img) { window.loadLazyNode(img); }); } function formatRecharge(raw) { var n = Math.floor(Number(raw)); if (!isFinite(n) || n < 0) n = 0; var s = String(n); if (s.length <= 3) return s; var out = []; var rem = s.length % 3; if (rem) out.push(s.slice(0, rem)); for (var i = rem; i < s.length; i += 3) out.push(s.slice(i, i + 3)); return out.join(","); } function syncHeaderUser() { var session = window.CookieUtil && typeof CookieUtil.getAuthSession === "function" ? CookieUtil.getAuthSession() : null; if (!session) return; var avatar = usableAvatar(session.avatar); document.querySelectorAll("[data-header-avatar]").forEach(function (img) { if (avatar) setAvatarImg(img, avatar); }); var name = String(session.nickName || session.accountNo || "").trim(); if (name) { document.querySelectorAll(".user-chip__name, .user-menu__meta strong, .drawer__meta strong").forEach(function (el) { el.textContent = name; }); } if (session.userId) { document.querySelectorAll(".user-menu__meta span, .drawer__meta span").forEach(function (el) { if (/^ID\b/.test(String(el.textContent || "").trim())) { el.textContent = "ID " + session.userId; } }); } if (Object.prototype.hasOwnProperty.call(session, "recharge") && session.recharge !== "") { var text = formatRecharge(session.recharge); document.querySelectorAll("[data-header-recharge]").forEach(function (el) { el.textContent = text; }); } refreshAvatarDecrypt(document); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", syncHeaderUser); } else { syncHeaderUser(); } document.addEventListener("auth:login", syncHeaderUser); document.addEventListener("auth:logout", syncHeaderUser); window.refreshAvatarDecrypt = refreshAvatarDecrypt; window.setAvatarImg = setAvatarImg; window.syncHeaderUser = syncHeaderUser; })();