(function () { var HISTORY_KEY = "hgdj_search_history"; var HISTORY_MAX = 10; var PLACEHOLDER_IMG = "/static/images/placeholder.png?v=2"; var input = document.querySelector("[data-mobile-search-input]"); var form = input && input.closest("form"); var clear = document.querySelector("[data-mobile-search-clear]"); var defaultView = document.querySelector("[data-search-default]"); var suggestions = document.querySelector("[data-search-suggestions]"); var suggestList = document.querySelector("[data-search-suggest-list]"); var history = document.querySelector("[data-search-history]"); var historyChips = document.querySelector("[data-history-chips]"); var historyClear = document.querySelector("[data-history-clear]"); if (!input || !form || !clear || !defaultView || !suggestions || !suggestList) return; var suggestTimer = null; var suggestSeq = 0; function searchResultsPath(q) { q = String(q || "").trim(); if (!q) return "/search"; return "/search/" + encodeURIComponent(q); } 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 readHistory() { try { var raw = window.localStorage.getItem(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, HISTORY_MAX); } catch (_) { return []; } } function writeHistory(list) { try { window.localStorage.setItem(HISTORY_KEY, JSON.stringify(list.slice(0, HISTORY_MAX))); } catch (_) { /* ignore quota / private mode */ } } function pushHistory(q) { q = String(q || "").trim(); if (!q) return; var list = readHistory().filter(function (item) { return item !== q; }); list.unshift(q); writeHistory(list); } function clearHistory() { try { window.localStorage.removeItem(HISTORY_KEY); } catch (_) { /* ignore */ } } function renderHistory() { if (!history || !historyChips) return; var list = readHistory(); historyChips.innerHTML = ""; if (!list.length) { history.hidden = true; return; } history.hidden = false; list.forEach(function (term) { var link = document.createElement("a"); link.className = "mobile-search__chip"; link.href = searchResultsPath(term); link.textContent = term; historyChips.appendChild(link); }); } function renderSuggest(data, keyword) { 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) + "

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

暂无相关结果,可直接搜索“' + escapeHtml(keyword) + '”

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

搜索中…

'; 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 syncPanels() { var query = input.value.trim(); var hasQuery = query.length > 0; defaultView.hidden = hasQuery; suggestions.hidden = !hasQuery; clear.hidden = !hasQuery; if (!hasQuery) { suggestSeq += 1; suggestList.innerHTML = ""; } } function scheduleSuggest() { syncPanels(); var q = input.value.trim(); if (suggestTimer) clearTimeout(suggestTimer); if (!q) return; suggestTimer = setTimeout(function () { suggestTimer = null; fetchSuggest(q); }, 220); } input.addEventListener("input", scheduleSuggest); clear.addEventListener("click", function () { input.value = ""; input.dispatchEvent(new Event("input")); input.focus(); }); form.addEventListener("submit", function (event) { event.preventDefault(); var q = input.value.trim(); if (!q) { input.focus(); return; } pushHistory(q); window.location.href = searchResultsPath(q); }); if (historyClear && history) { historyClear.addEventListener("click", function () { clearHistory(); renderHistory(); }); } // 从联想 / 热搜跳转搜索结果时也写入本地历史 document.addEventListener("click", function (event) { var link = event.target.closest("a[data-suggest-query], a[href^='/search/']"); if (!link || link.hasAttribute("data-search-close")) return; var q = String(link.getAttribute("data-suggest-query") || "").trim(); if (!q) { var href = link.getAttribute("href") || ""; var match = href.match(/^\/search\/([^/?#]+)/); if (!match) return; try { q = decodeURIComponent(match[1]); } catch (_) { q = match[1]; } } if (q) pushHistory(q); }); document.querySelectorAll("[data-search-close]").forEach(function (link) { link.addEventListener("click", function (event) { if (!document.referrer) return; try { if (new URL(document.referrer).origin === window.location.origin) { event.preventDefault(); window.history.back(); } } catch (_) { /* Use the link destination when the referrer cannot be read. */ } }); }); renderHistory(); syncPanels(); if (input.value.trim()) { fetchSuggest(input.value.trim()); } })();