diff --git a/assets/css/frontend/nav/mobile-toggle.css b/assets/css/frontend/nav/mobile-toggle.css index 24f200a8..eb4e45d7 100644 --- a/assets/css/frontend/nav/mobile-toggle.css +++ b/assets/css/frontend/nav/mobile-toggle.css @@ -553,6 +553,73 @@ font-size: 0.75rem; } +.nav-searchbox__meta { + display: grid; + gap: 10px; + margin-top: 12px; +} + +.nav-searchbox__types { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.nav-searchbox__type { + display: inline-flex; + align-items: center; + min-height: 32px; + padding: 0 12px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink-3); + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; +} + +.nav-searchbox__type.is-active { + border-color: var(--color-primary); + background: var(--color-primary-soft); + color: var(--color-primary); +} + +.nav-searchbox__category-wrap { + position: relative; +} + +.nav-searchbox__category { + appearance: none; + width: 100%; + min-height: 36px; + padding: 0 34px 0 12px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill, 999px); + background: var(--surface-2); + color: var(--color-ink); + font: 500 0.875rem/1 var(--font-ui); +} + +.nav-searchbox__category-wrap::after { + content: ''; + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid var(--color-ink-3); + pointer-events: none; +} + +.nav-searchbox__category:disabled { + opacity: 0.56; + cursor: not-allowed; +} + .nav-drawer__menu { flex: 1; padding: 16px 20px 32px; diff --git a/assets/css/routes/search.css b/assets/css/routes/search.css index d346d830..8d5cd6bc 100644 --- a/assets/css/routes/search.css +++ b/assets/css/routes/search.css @@ -242,13 +242,76 @@ outline: none; } -/* ========== 关键词高亮 ========== */ -.item-heading mark, -.item-excerpt mark { - background: color-mix(in srgb, var(--color-primary) 18%, transparent); - color: inherit; - border-radius: 4px; - padding: 0 0.15em; + +.search-page-form__meta { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 12px; + margin: 0 0 16px; +} + +.search-page-form__types { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.search-page-form__type { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill); + background: var(--surface-2); + color: var(--color-ink-3); + font-weight: 500; + cursor: pointer; + transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease; +} + +.search-page-form__type:hover, +.search-page-form__type.is-active { + border-color: var(--color-primary); + color: var(--color-primary); + background: var(--color-primary-soft, rgba(59, 130, 246, 0.12)); +} + +.search-page-form__category-wrap { + position: relative; +} + +.search-page-form__category { + appearance: none; + min-height: 36px; + padding: 0 34px 0 14px; + border: 1px solid var(--color-line); + border-radius: var(--radius-pill); + background: var(--surface-2); + color: var(--color-ink); + font: 500 14px/1 var(--font-ui); + cursor: pointer; +} + +.search-page-form__category-wrap::after { + content: ''; + position: absolute; + right: 12px; + top: 50%; + transform: translateY(-50%); + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid var(--color-ink-3); + pointer-events: none; +} + +.search-page-form__category:disabled { + opacity: 0.56; + cursor: not-allowed; } /* ========== 空状态 ========== */ @@ -339,6 +402,19 @@ padding: 0 14px; } + .search-page-form__meta { + flex-direction: column; + align-items: stretch; + } + + .search-page-form__category-wrap { + width: 100%; + } + + .search-page-form__category { + width: 100%; + } + .search-page-toolbar { flex-direction: column; align-items: flex-start; diff --git a/assets/js/core/article.js b/assets/js/core/article.js index 68ae4cfa..cd5f4bb6 100644 --- a/assets/js/core/article.js +++ b/assets/js/core/article.js @@ -49,6 +49,9 @@ } else { url.searchParams.delete("aksrt_category"); } + if (url.searchParams.get("aksrt_search_type") && url.searchParams.get("aksrt_search_type") !== "post") { + url.searchParams.delete("aksrt_category"); + } url.searchParams.delete("paged"); window.location.href = url.toString(); }); diff --git a/assets/js/core/search.js b/assets/js/core/search.js index e4f1fa3a..1e9c49d4 100644 --- a/assets/js/core/search.js +++ b/assets/js/core/search.js @@ -5,8 +5,6 @@ "use strict"; function initSearchPanel() { - var btn = document.getElementById("search-toggle"); - var panel = document.getElementById("nav-search-panel"); var mobileOverlay = document.getElementById("tabbar-search-overlay"); var mobileInput = document.getElementById("tabbar-search-input"); var mobileClose = document.getElementById("tabbar-search-close"); @@ -18,7 +16,8 @@ var historyClear = document.getElementById("tabbar-search-history-clear"); var suggestionsWrap = document.getElementById("tabbar-search-suggestions"); var suggestionsSection = document.getElementById("tabbar-search-suggestions-section"); - if (!btn || !panel) return; + var searchForms = Array.prototype.slice.call(document.querySelectorAll("[data-aksrt-search-form]")); + if (!searchForms.length && !mobileForm) return; var HISTORY_KEY = "aksrt-mobile-search-history"; var suggestTimer = null; var searchConfig = (window.aksrtData && aksrtData.search) || {}; @@ -32,20 +31,66 @@ suggestionsSection.hidden = true; } + function getDesktopSearchType() { + if (!searchForms.length) return searchConfig.defaultType || "post"; + var input = searchForms[0].querySelector('input[name="aksrt_search_type"]'); + var value = input ? (input.value || "") : ""; + return value || searchConfig.defaultType || "post"; + } + + function getDesktopCategory() { + if (!searchForms.length) return "0"; + var input = searchForms[0].querySelector('input[name="aksrt_category"]'); + return input ? (input.value || "0") : "0"; + } + + function syncSearchForms(type, category) { + searchForms.forEach(function (form) { + var typeInput = form.querySelector('input[name="aksrt_search_type"]'); + if (typeInput) { + typeInput.value = type || searchConfig.defaultType || "post"; + } + var categoryInput = form.querySelector('input[name="aksrt_category"]'); + if (categoryInput) { + if ((type || searchConfig.defaultType || "post") === "post" && category && category !== "0") { + categoryInput.value = category; + } else { + categoryInput.value = ""; + } + } + form.querySelectorAll("[data-search-type]").forEach(function (button) { + button.classList.toggle("is-active", button.getAttribute("data-search-type") === (type || searchConfig.defaultType || "post")); + }); + }); + } + + function syncCategorySelectors(type, category) { + document.querySelectorAll("[data-search-category-select]").forEach(function (select) { + select.value = category && category !== "" ? category : "0"; + select.disabled = (type || searchConfig.defaultType || "post") !== "post"; + }); + } + + function getSearchType() { - return mobileTypeInput ? (mobileTypeInput.value || "post") : "post"; + if (mobileTypeInput) { + return mobileTypeInput.value || getDesktopSearchType(); + } + return getDesktopSearchType(); } function setSearchType(type) { - if (!mobileTypeInput) return; - mobileTypeInput.value = type; + var nextType = type || searchConfig.defaultType || getDesktopSearchType(); + if (mobileTypeInput) { + mobileTypeInput.value = nextType; + } mobileTypeButtons.forEach(function (button) { - button.classList.toggle("is-active", button.getAttribute("data-search-type") === type); + button.classList.toggle("is-active", button.getAttribute("data-search-type") === nextType); }); + syncSearchForms(nextType, getDesktopCategory()); + syncCategorySelectors(nextType, getDesktopCategory()); requestSuggestions(); } - - function readHistory() { if (!historyEnabled) return []; if (aksrtData.isLoggedIn) return []; try { @@ -218,34 +263,10 @@ document.body.classList.remove("tabbar-search-open"); if (suggestionsSection) suggestionsSection.hidden = true; } - btn.setAttribute("aria-expanded", open ? "true" : "false"); return; } - - panel.classList.toggle("is-open", open); - btn.setAttribute("aria-expanded", open ? "true" : "false"); - if (open) { - var input = panel.querySelector('input[type="search"]'); - if (input) input.focus(); - } } - btn.addEventListener("click", function (e) { - e.stopPropagation(); - if (isMobileSearchMode()) { - setOpen(!mobileOverlay || mobileOverlay.hasAttribute("hidden")); - return; - } - setOpen(!panel.classList.contains("is-open")); - }); - - document.addEventListener("click", function (e) { - if (isMobileSearchMode()) return; - if (!panel.classList.contains("is-open")) return; - if (panel.contains(e.target) || btn.contains(e.target)) return; - setOpen(false); - }); - if (mobileOverlay) { mobileOverlay.addEventListener("click", function (e) { if (e.target === mobileOverlay) setOpen(false); @@ -280,6 +301,14 @@ }); } + document.querySelectorAll("[data-search-category-select]").forEach(function (select) { + select.addEventListener("change", function () { + var nextCategory = this.value || "0"; + syncSearchForms(getSearchType(), nextCategory); + syncCategorySelectors(getSearchType(), nextCategory); + }); + }); + mobileTypeButtons.forEach(function (button) { button.addEventListener("click", function () { setSearchType(button.getAttribute("data-search-type") || "post"); @@ -298,18 +327,20 @@ }); } - document.querySelectorAll("[data-aksrt-search-form]").forEach(function (form) { + searchForms.forEach(function (form) { if (form === mobileForm) return; form.addEventListener("submit", function () { if (!historyEnabled) return; var input = form.querySelector('input[name="s"]'); var typeInput = form.querySelector('input[name="aksrt_search_type"]'); var keyword = input ? (input.value || "").trim() : ""; - var type = typeInput ? (typeInput.value || "post") : "post"; + var type = typeInput ? (typeInput.value || searchConfig.defaultType || "post") : (searchConfig.defaultType || "post"); pushHistory(keyword, type); }); }); + syncSearchForms(getSearchType(), getDesktopCategory()); + syncCategorySelectors(getSearchType(), getDesktopCategory()); setSearchType(getSearchType()); if (historyEnabled && aksrtData.isLoggedIn) { requestHistorySync("get", null, function (items) { @@ -318,17 +349,8 @@ } document.addEventListener("keydown", function (e) { - if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { - e.preventDefault(); - setOpen(true); - } - if (e.key === "Escape" && panel.classList.contains("is-open")) { - setOpen(false); - btn.focus(); - } if (e.key === "Escape" && isMobileSearchMode() && mobileOverlay && !mobileOverlay.hasAttribute("hidden")) { setOpen(false); - btn.focus(); } }); diff --git a/header.php b/header.php index ac7141d6..271976e5 100644 --- a/header.php +++ b/header.php @@ -118,8 +118,21 @@ if (!empty($aksrt_bg_styles)) { $aksrt_logo_url = function_exists('aksrt_get_site_logo_url') ? trim((string) aksrt_get_site_logo_url()) : ''; $aksrt_logo_dark_url = function_exists('aksrt_get_site_logo_dark_url') ? trim((string) aksrt_get_site_logo_dark_url()) : ''; $aksrt_logo_width = function_exists('aksrt_get_site_logo_width') ? aksrt_get_site_logo_width() : 150; + $aksrt_search_state = function_exists('aksrt_get_search_form_state') + ? aksrt_get_search_form_state() + : [ + 'type' => 'post', + 'types' => ['post' => __('文章', 'aksrt')], + 'category_id' => 0, + 'category_enabled' => false, + 'categories' => [], + ]; $aksrt_search_placeholder = function_exists('aksrt_get_search_placeholder') ? aksrt_get_search_placeholder() : __('开启精彩搜索', 'aksrt'); - $aksrt_search_type = function_exists('aksrt_get_search_form_type') ? aksrt_get_search_form_type() : 'post'; + $aksrt_search_type = $aksrt_search_state['type']; + $aksrt_search_type_options = $aksrt_search_state['types']; + $aksrt_search_category_enabled = !empty($aksrt_search_state['category_enabled']); + $aksrt_search_category_id = (int) ($aksrt_search_state['category_id'] ?? 0); + $aksrt_search_categories = is_array($aksrt_search_state['categories'] ?? null) ? $aksrt_search_state['categories'] : []; $aksrt_search_hot_keywords = function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : []; $aksrt_brand_logo_src = ''; $aksrt_mobile_menu_location = has_nav_menu('mobile') ? 'mobile' : 'primary'; @@ -208,8 +221,11 @@ if (!empty($aksrt_bg_styles)) {